Skip to content

Instantly share code, notes, and snippets.

@mattmccray
Last active August 29, 2015 13:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mattmccray/9439877 to your computer and use it in GitHub Desktop.
Save mattmccray/9439877 to your computer and use it in GitHub Desktop.
Build React Components using natural CoffeeScript syntax.
# Public: Define components as CoffeeScript classes
#
# Example:
#
# class UserChip extends Component
#
# @staticMethod: -> # becomes a static method on the React Component
# "hello"
#
# render: ->
# (@div null, "Hello")
#
# # This will create the React component based on the class definition,
# # including translating (@div XXX) calls into React.DOM.div(XXX) calls.
# module.exports= UserChip.reactify()
#
module.exports=
class Component
@reactify: (componentClass=this)->
React.createClass extractMethods componentClass
extractMethods= (comp)->
methods= extractInto {}, comp::
methods.displayName= comp.name or comp.displayName or 'UnnamedComponent'
methods.statics= extractInto Class:comp, comp
methods
extractInto= (target, source)->
for key,val of source
continue if key in ignoredKeys
target[key]= translateTagCalls val
target
ignoredKeys= '__super__ constructor reactify'.split ' '
tagParser= /this\.(\w*)\(/g
translateTagCalls= (fn)->
return fn unless typeof(fn) is 'function'
source= fn.toString()
compiled= source.replace tagParser, (fragment, tag)->
if React.DOM[ tag ]? then "React.DOM.#{ tag }(" else fragment
if compiled isnt source
eval "(#{ compiled })" # Yes, this uses eval. Deal with it.
else
fn
@mattmccray
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment