├── .gitignore ├── .jscsrc ├── .jshintrc ├── Gruntfile.js ├── LICENSE ├── README.md ├── example ├── index.html ├── perf.html ├── react.html └── react │ ├── react.js │ └── reactdom.js ├── package.json ├── psuedo-code └── flow.md ├── src ├── Tembo.js ├── core │ └── Tembo.core.can.js ├── interface │ ├── Component.js │ └── Patch.js ├── render │ ├── NativeRoot.js │ ├── ShadowNode.js │ └── util.js ├── renderers │ ├── Blessed.js │ ├── DOM.js │ ├── String.js │ └── Test.js └── updaters │ ├── BatchUpdate.js │ └── SyncUpdate.js └── tests ├── component ├── index.js ├── mount.js ├── unmount.js └── update.js ├── patch ├── component.js ├── falsy.js ├── index.js ├── native-element.js └── string.js └── util.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 18 | .grunt 19 | 20 | # node-waf configuration 21 | .lock-wscript 22 | 23 | # Compiled binary addons (http://nodejs.org/api/addons.html) 24 | build/Release 25 | dist 26 | 27 | # Dependency directory 28 | node_modules 29 | 30 | # Optional npm cache directory 31 | .npm 32 | 33 | # Optional REPL history 34 | .node_repl_history 35 | 36 | .DS_Store 37 | -------------------------------------------------------------------------------- /.jscsrc: -------------------------------------------------------------------------------- 1 | { 2 | "preset": "airbnb", 3 | "disallowSpaceAfterKeywords": ["else", "function", "while", "for"], 4 | "requireSpaceAfterKeywords" : ["if", "return"], 5 | "requireSpaceBeforeBlockStatements": false, 6 | "disallowSpaceBeforeBlockStatements": true, 7 | 8 | "requireSpaceBetweenArguments": false, 9 | "disallowSpaceBetweenArguments": true, 10 | 11 | "requireSpaceAfterComma": false, 12 | "disallowSpaceAfterComma": true, 13 | 14 | "requireTrailingComma": false, 15 | "disallowTrailingComma": true, 16 | 17 | "disallowSpaceAfterObjectKeys": false, 18 | "requireSpaceAfterObjectKeys": true, 19 | 20 | "requireSpaceBeforeBinaryOperators": false, 21 | "requireSpaceAfterBinaryOperators": false, 22 | 23 | "requirePaddingNewLinesAfterBlocks": false, 24 | "disallowMultipleVarDecl": false, 25 | "requireCamelCaseOrUpperCaseIdentifiers": false, 26 | "requireSpacesInAnonymousFunctionExpression": false, 27 | "disallowSpacesInAnonymousFunctionExpression": { 28 | "beforeOpeningRoundBrace": true, 29 | "beforeOpeningCurlyBrace": true 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "globals":{ 3 | "console": true 4 | }, 5 | "browserify": true, 6 | "shadow": true, 7 | "forin": true, 8 | "funcscope": true, 9 | "latedef": true, 10 | "unused": true, 11 | "undef": true 12 | } 13 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function(grunt){ 2 | 'use strict'; 3 | 4 | var tasks = [ 5 | 'grunt-contrib-jshint', 6 | 'grunt-contrib-concat', 7 | 'grunt-browserify', 8 | 'grunt-tape', 9 | 'grunt-contrib-jasmine', 10 | 'grunt-contrib-watch', 11 | 'grunt-contrib-uglify', 12 | 'grunt-jscs' 13 | ]; 14 | 15 | var config = {}; 16 | 17 | // ********************************************* 18 | // jshint 19 | config.jshint = {}; 20 | config.jshint.src = ['src/core/*.js','src/helpers/*.js','src/interface/*.js','src/defaultProperties/*.js']; 21 | config.jshint.test = ['tests/**/*.js','Gruntfile.js']; 22 | config.jshint.options = { 23 | jshintrc : true 24 | }; 25 | 26 | // ********************************************* 27 | // tape 28 | config.tape = { 29 | options : { 30 | pretty : false, 31 | output : 'console' 32 | }, 33 | files : ['tests/**/index.js'] 34 | }; 35 | 36 | // ********************************************* 37 | // browserify 38 | config.browserify = { 39 | dist : { 40 | files : { 41 | 'dist/tembo.js' : ['src/Tembo.js'] 42 | }, 43 | options : { 44 | standalone : true 45 | } 46 | } 47 | }; 48 | 49 | // ********************************************* 50 | // jscs 51 | config.jscs = { 52 | src : 'src/**/*.js', 53 | test : ['tests/**/*.js','Gruntfile.js'], 54 | options : { 55 | config : '.jscsrc' 56 | } 57 | }; 58 | 59 | // ********************************************* 60 | // concat 61 | // config.concat = { 62 | // dist: { 63 | // src: [ 64 | // 'src/Tembo.js', 65 | // 'src/core/*.js', 66 | // 'src/interface/*.js', 67 | // ], 68 | // dest: 'dist/tembo.js' 69 | // } 70 | // } 71 | 72 | // ********************************************* 73 | // uglify 74 | config.uglify = {}; 75 | config.uglify.all = { 76 | files : { 77 | 'dist/tembo.min.js' : ['dist/tembo.js'] 78 | }, 79 | options : { 80 | preserveComments : false, 81 | sourceMap : 'dist/tembo.min.map', 82 | sourceMappingURL : 'tembo.min.map', 83 | report : 'min', 84 | beautify : { 85 | ascii_only : true 86 | }, 87 | compress : { 88 | hoist_funs : false, 89 | loops : false, 90 | unused : false 91 | } 92 | } 93 | }; 94 | 95 | // ********************************************* 96 | // watch 97 | config.watch = {}; 98 | config.watch.scripts = { 99 | files : ['src/**/*.js','src/*.js'], 100 | tasks : ['default'], 101 | options : { 102 | spawn : false 103 | } 104 | }; 105 | 106 | grunt.initConfig(config); 107 | 108 | tasks.forEach(grunt.loadNpmTasks); 109 | 110 | grunt.registerTask('build',['browserify','uglify']); 111 | 112 | grunt.registerTask('hint',['jshint','jscs']); 113 | 114 | grunt.registerTask('test',['tape']); 115 | 116 | grunt.registerTask('default',['hint','test','browserify','uglify','watch']); 117 | 118 | }; 119 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Guilherme (Coder) de Souza 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Alt text](http://i.imgur.com/osPnYVh.png) 2 | # Tembo 3 | 4 | Tembo is my own react-like rendering engine implementation in 4kb. 5 | 6 | # [Live Demo / Performance Test](https://s3-sa-east-1.amazonaws.com/tembojs/perf.html) 7 | 8 | # API 9 | 10 | ##### Tembo.createClass(componentSpec) 11 | ```javascript 12 | const Message = Tembo.createClass({ 13 | getInitialState: function() { 14 | return { 15 | message: 'Hello Word' 16 | } 17 | }, 18 | render: function() { 19 | return Tembo.createElement('div', {}, this.state.message) 20 | } 21 | }) 22 | ``` 23 | ##### Tembo.createElement(temboComponentClass || domNodeName,props,children) 24 | ```javascript 25 | Tembo.createElement('div', {}, 'hello world') 26 | ``` 27 | ##### Tembo.render(temboComponent, DOMNode) 28 | ```javascript 29 | const component = Tembo.createElement(myMessage, {}, false) 30 | Tembo.render(component, document.getElementById('content')) 31 | ``` 32 | -------------------------------------------------------------------------------- /example/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 14 | 15 | 16 | 17 |
18 |
19 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /example/perf.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Document 6 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /example/react.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 14 | 15 | 16 | React 17 |
18 | 19 |
20 | 21 | 22 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /example/react/reactdom.js: -------------------------------------------------------------------------------- 1 | /** 2 | * ReactDOM v0.14.2 3 | * 4 | * Copyright 2013-2015, Facebook, Inc. 5 | * All rights reserved. 6 | * 7 | * This source code is licensed under the BSD-style license found in the 8 | * LICENSE file in the root directory of this source tree. An additional grant 9 | * of patent rights can be found in the PATENTS file in the same directory. 10 | * 11 | */ 12 | // Based off https://github.com/ForbesLindesay/umd/blob/master/template.js 13 | ;(function(f) { 14 | // CommonJS 15 | if (typeof exports === "object" && typeof module !== "undefined") { 16 | module.exports = f(require('react')); 17 | 18 | // RequireJS 19 | } else if (typeof define === "function" && define.amd) { 20 | define(['react'], f); 21 | 22 | //