Skip to content
This repository was archived by the owner on Feb 23, 2025. It is now read-only.

Commit d516ee7

Browse files
committed
v0.0.4
1 parent 3baeaf2 commit d516ee7

File tree

3 files changed

+163
-32
lines changed

3 files changed

+163
-32
lines changed

index.js

Lines changed: 105 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,17 @@
11
"use strict";
2+
var objectAssign = require("object-assign");
23
var parser = require("handlebars-html-parser");
4+
var React = require("react");
5+
var uglify = require("uglify-js");
6+
7+
var defaultOptions =
8+
{
9+
beautify: true,
10+
prefix: "",
11+
suffix: ""
12+
};
13+
14+
var createElementFunction = 'React.createElement(';
315

416

517

@@ -40,7 +52,9 @@ var parser = require("handlebars-html-parser");
4052

4153
function compiler(options)
4254
{
43-
this.parser = new parser(options);
55+
this.options = objectAssign({}, defaultOptions, options);
56+
57+
this.parser = new parser(this.options);
4458
}
4559

4660

@@ -50,7 +64,7 @@ compiler.prototype.compile = function(str)
5064
var attrCount,childrenCount/*,state*/;
5165
//var elementStack = [];
5266
var nodeStack = this.parser.parse(str);
53-
var result = '';
67+
var result = [];
5468

5569
console.log(nodeStack);
5670

@@ -92,12 +106,14 @@ compiler.prototype.compile = function(str)
92106
}
93107
case parser.type.HTML_ATTR_START:
94108
{
95-
result += ',';
109+
append(',', result);
110+
96111
if (attrCount++ === 0)
97112
{
98113
//state = "attrs";
99-
result += '{';
114+
append('{', result);
100115
}
116+
101117
break;
102118
}
103119

@@ -118,7 +134,7 @@ compiler.prototype.compile = function(str)
118134
}
119135
case parser.type.HTML_ATTR_VALUE_START:
120136
{
121-
result += ':';
137+
append(':', result);
122138
break;
123139
}
124140

@@ -135,11 +151,13 @@ compiler.prototype.compile = function(str)
135151

136152
case parser.type.HTML_TAG_END:
137153
{
138-
result += closeAttrs(nodeStack, nodeIndex);
139-
if (isClosingTag(nodeStack,nodeIndex,-4) === true)
154+
append( closeAttrs(nodeStack, nodeIndex), result );
155+
156+
if (isClosingTag(nodeStack, nodeIndex, -4) === true)
140157
{
141-
result += ')';
158+
append(')', result);
142159
}
160+
143161
break;
144162
}
145163
case parser.type.HTML_TAG_START:
@@ -148,9 +166,10 @@ compiler.prototype.compile = function(str)
148166
{
149167
attrCount = 0;
150168
childrenCount = 0;
151-
result += prefix(nodeStack, nodeIndex);
152-
result += 'React.createElement(';
169+
append( prefix(nodeStack, nodeIndex), result );
170+
append( createElementFunction, result );
153171
}
172+
154173
break;
155174
}
156175

@@ -167,11 +186,15 @@ compiler.prototype.compile = function(str)
167186

168187
case parser.type.TEXT:
169188
{
170-
if (isClosingTag(nodeStack,nodeIndex,-2) !== true)
189+
if (isClosingTag(nodeStack, nodeIndex, -2) !== true)
171190
{
172-
result += prefix(nodeStack, nodeIndex);
173-
result += '"'+ node.value +'"';
191+
//if (changeTagFunction(nodeStack, nodeIndex, node.value, result) === false)
192+
//{
193+
append( prefix(nodeStack, nodeIndex), result );
194+
append( '"'+ node.value +'"', result );
195+
//}
174196
}
197+
175198
break;
176199
}
177200

@@ -183,11 +206,49 @@ compiler.prototype.compile = function(str)
183206
}
184207
});
185208

186-
return result;
209+
return finalize(result, this.options);
187210
};
188211

189212

190213

214+
function append(string, resultArray)
215+
{
216+
if (string != null && string !== "")
217+
{
218+
resultArray.push(string);
219+
}
220+
}
221+
222+
223+
224+
function changeTagFunction(nodeStack, nodeIndex, tagName, resultArray)
225+
{
226+
var lastResultIndex;
227+
228+
// If we're defining a tag name
229+
if (previousNode(nodeStack,nodeIndex).type === parser.type.HTML_TAG_NAME_START)
230+
{
231+
lastResultIndex = resultArray.length-1;
232+
233+
// If last result index is `React.createElement`
234+
if (resultArray[lastResultIndex] === createElementFunction)
235+
{
236+
tagName = tagName.toLowerCase();
237+
238+
// If tag name has a `React.DOM` function
239+
if (typeof React.DOM[tagName] === "function")
240+
{
241+
resultArray[lastResultIndex] = 'React.DOM.' + tagName + '(';
242+
return true;
243+
}
244+
}
245+
}
246+
247+
return false;
248+
}
249+
250+
251+
191252
function closeAttrs(nodeStack, nodeIndex)
192253
{
193254
var prevNode = previousNode(nodeStack, nodeIndex);
@@ -205,6 +266,36 @@ function closeAttrs(nodeStack, nodeIndex)
205266

206267

207268

269+
function finalize(resultArray, options)
270+
{
271+
var js = options.prefix + resultArray.join("") + options.suffix;
272+
273+
// Check that the compiled JavaScript code is valid
274+
try
275+
{
276+
Function("", js);
277+
}
278+
catch (error)
279+
{
280+
console.log(js);
281+
throw error;
282+
}
283+
284+
if (options.beautify === true)
285+
{
286+
js = uglify.parse(js).print_to_string(
287+
{
288+
beautify: true,
289+
comments: true,
290+
indent_level: 2
291+
});
292+
}
293+
294+
return js;
295+
}
296+
297+
298+
208299
function isClosingTag(nodeStack, nodeIndex, numPrev)
209300
{
210301
var twoNodesBack = previousNode(nodeStack, nodeIndex, numPrev);

package.json

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "handlebars-react",
33
"description": "Compile Handlebars templates to React.",
4-
"version": "0.0.3",
4+
"version": "0.0.4",
55
"license": "MIT",
66
"homepage": "https://github.com/stevenvachon/handlebars-react",
77
"author": {
@@ -18,7 +18,10 @@
1818
"url": "https://github.com/stevenvachon/handlebars-react/issues"
1919
},
2020
"dependencies": {
21-
"handlebars-html-parser": "git://github.com/stevenvachon/handlebars-html-parser.git"
21+
"handlebars-html-parser": "git://github.com/stevenvachon/handlebars-html-parser.git",
22+
"object-assign": "^3.0.0",
23+
"react": "^0.13.3",
24+
"uglify-js": "^2.4.24"
2225
},
2326
"devDependencies": {
2427
"chai": "^3.2.0",
@@ -31,7 +34,8 @@
3134
"test": "mocha test/ --reporter spec --check-leaks --bail --no-exit"
3235
},
3336
"files": [
34-
"index.js"
37+
"index.js",
38+
"license"
3539
],
3640
"keywords": [
3741
"handlebars",

test/test.js

Lines changed: 51 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,28 +3,64 @@ var compiler = require("../");
33

44
var expect = require("chai").expect;
55

6+
var options = { beautify:false };
67

78

8-
it("should work", function(done)
9+
10+
describe("Basic HTML", function()
911
{
10-
var result = new compiler().compile('<tag attr="value">text</tag>');
12+
it("should support a tag", function(done)
13+
{
14+
var result = new compiler(options).compile('<tag></tag>');
15+
var expectedResult = 'React.createElement("tag")';
16+
17+
expect(result).to.equal(expectedResult);
18+
done();
19+
});
1120

12-
console.log(result);
1321

14-
//expect(result).to.equal();
1522

16-
done();
17-
});
18-
19-
20-
21-
it.skip("should work", function(done)
22-
{
23-
var result = new compiler().compile('<tag><tag/>text<tag/></tag>');
23+
it("should support a tag that has attributes", function(done)
24+
{
25+
var result = new compiler(options).compile('<tag attr="value"></tag>');
26+
var expectedResult = 'React.createElement("tag",{"attr":"value"})';
27+
28+
expect(result).to.equal(expectedResult);
29+
done();
30+
});
31+
32+
33+
34+
it("should support a tag that has attributes and text content", function(done)
35+
{
36+
var result = new compiler(options).compile('<tag attr="value">text</tag>');
37+
var expectedResult = 'React.createElement("tag",{"attr":"value"},"text")';
38+
39+
//console.log( require("uglify-js").minify(result,{fromString:true}) );
40+
41+
expect(result).to.equal(expectedResult);
42+
done();
43+
});
44+
45+
46+
47+
it("should support a tag that has nested tags", function(done)
48+
{
49+
var result = new compiler(options).compile('<tag><tag/>text<tag/></tag>');
50+
var expectedResult = 'React.createElement("tag",React.createElement("tag"),"text",React.createElement("tag"))';
51+
52+
expect(result).to.equal(expectedResult);
53+
done();
54+
});
2455

25-
console.log(result);
2656

27-
//expect(result).to.equal();
2857

29-
done();
58+
it.skip("should support a tag with a convenience function that has nested tags", function(done)
59+
{
60+
var result = new compiler(options).compile('<div><tag/>text<tag/></div>');
61+
var expectedResult = 'React.DOM.div(React.createElement("tag"),"text",React.createElement("tag"))';
62+
63+
expect(result).to.equal(expectedResult);
64+
done();
65+
});
3066
});

0 commit comments

Comments
 (0)