JSFiddle - React, Tailwind, and code Playground

by fresheyeball

HTML

<script src="http://cdnjs.cloudflare.com/ajax/libs/mocha/1.12.1/mocha.js"></script>
<script src="http://chaijs.com/chai.js"></script>
<link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/mocha/1.12.1/mocha.css">
<script src="//cdnjs.cloudflare.com/ajax/libs/lodash.js/2.4.1/lodash.js"></script>
<script>
    mocha.setup('bdd');
</script>
<body>
    <div id="mocha"></div>
</body>

CoffeeScript

Object.defineProperty Function::, 'def', 
    enumerable : false
    value : (name, config={}) ->        
        {get, set, init, derived} = config
        
        _NAME = "_#{name}"
        
        isDerived    = derived or false
        isPrivate    = (_.first(name) is '_')
        isConstant   = (name.toUpperCase() is name)        
        
        if not isDerived and not isConstant
            Object.defineProperty @::, _NAME,
                enumerable   : no
                value        : null
                writable     : true     

            attachClone = ->
                @[_NAME] ?= _.cloneDeep init if init?
                return
                
            get ?=       -> 
                attachClone.call @
                @[_NAME]
            set ?= (val) -> 
                attachClone.call @
                @[_NAME] = val
        
        Object.defineProperty @::, name, do ->
            if isConstant
                enumerable   : not isPrivate
                get          : -> init
                set          : -> throw new Error "Can't set .#{name} is a constant"
            else            
                enumerable   : not isPrivate
                get          : get
                set          : set

{expect} = chai

describe 'def', ->
    
    describe 'basic', ->
        Person = null 
        beforeEach ->
            class Person
                @def 'name'
    
        it 'should define the property', ->   
        
            person = new Person()
            expect(person).to.have.property 'name'
            expect(person.name).to.be.null
            
        it 'should not share state between instances', ->
            
            person1 = new Person()
            person2 = new Person()
            
            expect(person1.name).to.be.null
            expect(person2.name).to.be.null
            
            person1.name = "Jack"
            
            expect(person1.name).to.equal "Jack"            
           ...