Skip to content

Instantly share code, notes, and snippets.

@andreypopp
Created October 16, 2013 12:24
Show Gist options
  • Save andreypopp/7006888 to your computer and use it in GitHub Desktop.
Save andreypopp/7006888 to your computer and use it in GitHub Desktop.
var Page = React.createClass({
render: function() {
return markup html {
head {
meta(charset="utf8")
title { "Page" }
}
body {
div(className="wrapper")
}
}
}
});
macro attributes {
case {_()} => {
return #{null}
}
case {_($($name:ident = $val:expr) (,) ...)} => {
return [makeDelim('{}', #{$($name: $val) (,) ...})]
}
}
macro markupChildren {
case {_ $blocks...} => {
var nodes = #{$blocks ...},
children = [];
function splitNodes(nodes) {
var result = [],
cur = [];
function sameLine(tok) {
var last = cur[cur.length - 1].token;
return (last.lineNumber || last.endLineNumber) === (tok.lineNumber || tok.startLineNumber);
}
nodes.forEach(function(node) {
if (cur.length > 0 && !sameLine(node.token)) {
result.push(cur);
cur = []
}
if (isPunc(node, ';')) {
result.push(cur);
cur = [];
return;
}
cur.push(node);
});
result.push(cur);
return result;
}
function isDelim(expr, typ) {
return (expr.token.type === 9 && expr.token.value === typ);
}
function isPunc(expr, typ) {
return (expr.token.type === 7 && expr.token.value === typ);
}
function isComponent(expr) {
switch (expr.length) {
case 3:
return (expr[0].token.type === 3 && isDelim(expr[1], '()') && isDelim(expr[2], '{}'));
break;
case 2:
return (expr[0].token.type === 3 && isDelim(expr[1], '()')) ||
(expr[0].token.type === 3 && isDelim(expr[1], '{}'));
break;
case 2:
return (expr[0].token.type === 3 && isDelim(expr[1], '()')) ||
(expr[0].token.type === 3 && isDelim(expr[1], '{}'));
break;
}
}
function prevTokenOnSameLine() {
return (children[children.length - 1]
&& children[children.length - 1].token.lineNumber !== nodes[0].token.lineNumber)
}
var insertComma = true;
while (nodes.length > 0) {
var cur = nodes.slice(0, 3);
while (cur.length > 0) {
if (isComponent(cur))
break;
cur = cur.slice(0, cur.length - 1);
}
if (cur.length === 0) {
if (insertComma || prevTokenOnSameLine())
children.push(makePunc(','));
children.push(nodes[0]);
nodes = nodes.slice(1);
insertComma = false;
} else {
children.push(makePunc(','));
children = children.concat(#{markup}, nodes.slice(0, cur.length));
nodes = nodes.slice(cur.length);
insertComma = true;
}
}
return children;
}
}
macro markup {
case {_ $tag:ident ($attrs ...) {$blocks ...} } => {
var tag = #{ React.DOM.$tag };
var attrs = #{ attributes($attrs ...) };
var children = #{ markupChildren $blocks ... };
return tag.concat(makeDelim('()', attrs.concat(children)));
}
case {_ $tag:ident ($attrs ...) } => {
return #{ React.DOM.$tag(attributes($attrs ...)) }
}
case {_ $tag:ident {$blocks ...} } => {
var tag = #{ React.DOM.$tag };
var children = #{ markupChildren $blocks ... };
var attrs = #{ attributes() };
return tag.concat(makeDelim('()', attrs.concat(children)));
}
case {_ $tag:ident } => {
return #{ React.DOM.$tag(attributes()) }
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment