Skip to content
Browse files

initial

  • Loading branch information...
0 parents commit 2e2d4c19d9dd7e568fcfddeedefbae2fd075f72b @elmerbulthuis committed
0 build.js
No changes.
99 lib/html.js
@@ -0,0 +1,99 @@
+/*!
+ * html
+ * Copyright(c) 2011 Elmer Bulthuis <elmerbulthuis@gmail.com>
+ * MIT Licensed
+ */
+var special = {
+ 34: '&quot;',
+ 38: '&amp;',
+ //39: '&apos;',
+ 60: '&lt;',
+ 62: '&gt;',
+ 160: '&nbsp;'
+};
+var htmlReady = {};
+
+function encode(value) {
+ if (!value) return '';
+ if (value[htmlReady]) return value;
+ var buffer = '';
+ var charList = String(value);
+ var charCount = charList.length;
+ for (var charIndex = 0; charIndex < charCount; charIndex++) {
+ var charCode = charList.charCodeAt(charIndex);
+ if (charCode in special) {
+ buffer += special[charCode];
+ }
+ else {
+ //if (charCode < 32) continue;
+ if (charCode > 127) buffer += '&#' + charCode.toString() + ';';
+ else buffer += String.fromCharCode(charCode);
+ }
+ }
+ buffer[htmlReady] = true;
+ return buffer;
+}
+
+function raw(value) {
+ if (!value) return '';
+ if (value[htmlReady]) return value;
+ var buffer=new String(value);
+ buffer[htmlReady] = true;
+ return buffer;
+}
+var tagStack = [];
+
+function atomicTag(tag, attributeSet) {
+ var attributeText = attr(attributeSet);
+ return raw('<' + tag + (attributeText ? (' ' + attributeText ): '') +'/>');
+}
+
+function openTag(tag, attributeSet) {
+ tagStack.unshift(tag);
+ var attributeText = attr(attributeSet);
+ return raw('<' + tag + (attributeText ? (' ' + attributeText) : '') + '>');
+}
+
+function closeTag() {
+ var tag = tagStack.shift(tag);
+ return raw('</' + tag + '>');
+}
+
+function tag() {
+ if (arguments.length == 1) {
+ if (arguments[0] === true) return closeTag();
+ return openTag(arguments[0]);
+ }
+ if (arguments.length == 2) {
+ if (arguments[1] === true) return atomicTag(arguments[0]);
+ if (typeof arguments[1] != 'Object') return raw(openTag(arguments[0]) + encode(arguments[1]) + closeTag());
+ return openTag(arguments[0], arguments[1]);
+ }
+ if (arguments.length == 3) {
+ if (arguments[2] === true) return atomicTag(arguments[0], arguments[1]);
+ if (typeof arguments[2] != 'Object') return raw(openTag(arguments[0], arguments[1]) + encode(arguments[2]) + closeTag());
+ }
+ throw 'error';
+}
+
+function attr(attributeSet) {
+ var attributeList = [];
+ for (var attributeName in attributeSet) {
+ var attributeValue = attributeSet[attributeName];
+ switch (attributeValue) {
+ case true:
+ attributeList.push('' + attributeName + '="' + attributeName + '"');
+ break;
+ case false:
+ break;
+ default:
+ attributeList.push('' + attributeName + '="' + encode(attributeValue) + '"');
+ }
+ }
+ return raw(attributeList.join(' '));
+}
+//exports
+exports.encode = encode;
+exports.raw = raw;
+exports.tag = tag;
+exports.attr = attr;
340 lib/jsHtmlParser.js
@@ -0,0 +1,340 @@
+/*!
+ * jsHtmlParser
+ * Copyright(c) 2011 Elmer Bulthuis <elmerbulthuis@gmail.com>
+ * MIT Licensed
+ */
+var assert = require('assert');
+var tokenizer = require('./tokenizer');
+var html = require('./html');
+var rule = (function() {
+ var source = {
+ 'AnchorEscaped': /@(@+)/,
+ 'AnchorIfElse': /@if\(/,
+ 'AnchorIfElse1': /\)\s*\{/,
+ 'AnchorIfElse2': /\}\s*(else\s*\{)?/,
+ 'AnchorIfElse3': /\}/,
+ 'AnchorFor': /@for\(/,
+ 'AnchorFor1': /\)\s*\{/,
+ 'AnchorFor2': /\}/,
+ 'AnchorWhile': /@while\(/,
+ 'AnchorWhile1': /\)\s*\{/,
+ 'AnchorWhile2': /\}/,
+ 'AnchorDoWhile': /@do\s*\{/,
+ 'AnchorDoWhile1': /\}\s*while\(/,
+ 'AnchorDoWhile2': /\)/,
+ 'AnchorSwitch': /@switch\(/,
+ 'AnchorSwitch1': /\)\s*\{/,
+ 'AnchorSwitch2': /\}/,
+ 'AnchorWith': /@with\(/,
+ 'AnchorWith1': /\)\s*\{/,
+ 'AnchorWith2': /\}/,
+ 'AnchorGroupOpen': /@\(/,
+ 'AnchorGroupClose': /\)/,
+ 'AnchorBlockOpen': /@\{/,
+ 'AnchorBlockClose': /\}/,
+ 'AnchorInlineOpen': /@([$_A-Za-z][$_A-Za-z0-9]*)/,
+ //'AnchorInlineClose': /^(?!\.[$_A-Za-z][$_A-Za-z0-9]*)/,
+ 'AnchorInlineClose': /^/,
+ 'TextOpen': /<text>/,
+ 'TextClose': /<\/text>/,
+ 'TagEnter': /<([A-z]+)/,
+ 'TagRecurse': /<([A-z]+)/,
+ 'TagExit': /\s*\/>/,
+ 'TagExitOpen': /\s*>/,
+ 'TagClose': /<\/([A-z]+)>/,
+ 'JsMemberOpen': /^\.([$_A-Za-z][$_A-Za-z0-9]*)/,
+ //'JsMemberClose': /^(?!\.[$_A-Za-z][$_A-Za-z0-9]*)/,
+ 'JsMemberClose': /^/,
+ 'JsBlockOpen': /\{/,
+ 'JsBlockClose': /\}/,
+ 'JsGroupOpen': /\(/,
+ 'JsGroupClose': /\)/,
+ 'JsArrayOpen': /\[/,
+ 'JsArrayClose': /\]/,
+ 'JsDoubleQuoteOpen': /"/,
+ 'JsDoubleQuoteClose': /"/,
+ 'JsSingleQuoteOpen': /'/,
+ 'JsSingleQuoteClose': /'/,
+ 'JsStringEscaped': /\\./
+ };
+
+ function build() {
+ var ruleSet = {};
+ var argumentCount = arguments.length;
+ for (var argumentIndex = 0; argumentIndex < argumentCount; argumentIndex++) {
+ var argument = arguments[argumentIndex];
+ ruleSet[argument] = source[argument];
+ }
+ return ruleSet;
+ }
+ return {
+ root: build('AnchorEscaped', 'AnchorIfElse', 'AnchorFor', 'AnchorWhile', 'AnchorDoWhile', 'AnchorSwitch', 'AnchorWith', 'AnchorGroupOpen', 'AnchorBlockOpen', 'AnchorInlineOpen'),
+ text: build('AnchorEscaped', 'AnchorIfElse', 'AnchorFor', 'AnchorWhile', 'AnchorDoWhile', 'AnchorSwitch', 'AnchorWith', 'AnchorGroupOpen', 'AnchorBlockOpen', 'AnchorInlineOpen', 'TextClose'),
+
+ tagHead: build('AnchorEscaped', 'AnchorIfElse', 'AnchorFor', 'AnchorWhile', 'AnchorDoWhile', 'AnchorSwitch', 'AnchorWith', 'AnchorGroupOpen', 'AnchorBlockOpen', 'AnchorInlineOpen', 'TagExit', 'TagExitOpen'),
+ tag: build('AnchorEscaped', 'AnchorIfElse', 'AnchorFor', 'AnchorWhile', 'AnchorDoWhile', 'AnchorSwitch', 'AnchorWith', 'AnchorGroupOpen', 'AnchorBlockOpen', 'AnchorInlineOpen', 'TagRecurse', 'TagClose'),
+
+ anchorInline: build('JsMemberOpen', 'JsBlockOpen', 'JsGroupOpen', 'JsArrayOpen', 'AnchorInlineClose'),
+ anchorGroup: build('JsBlockOpen', 'JsGroupOpen', 'JsArrayOpen', 'JsSingleQuoteOpen', 'JsDoubleQuoteOpen','AnchorGroupClose'),
+ anchorBlock: build('JsBlockOpen', 'JsGroupOpen', 'JsArrayOpen','JsSingleQuoteOpen', 'JsDoubleQuoteOpen', 'TextOpen', 'TagEnter','AnchorBlockClose'),
+ anchorIfElse1: build('JsBlockOpen', 'JsGroupOpen', 'JsArrayOpen', 'JsSingleQuoteOpen', 'JsDoubleQuoteOpen', 'AnchorIfElse1'),
+ anchorIfElse2: build('JsBlockOpen', 'JsGroupOpen', 'JsArrayOpen', 'JsSingleQuoteOpen', 'JsDoubleQuoteOpen', 'TextOpen', 'TagEnter', 'AnchorIfElse2'),
+ anchorIfElse3: build('JsBlockOpen', 'JsGroupOpen', 'JsArrayOpen', 'JsSingleQuoteOpen', 'JsDoubleQuoteOpen', 'TextOpen', 'TagEnter', 'AnchorIfElse3'),
+ anchorFor1: build('JsBlockOpen', 'JsGroupOpen', 'JsArrayOpen', 'JsSingleQuoteOpen', 'JsDoubleQuoteOpen', 'AnchorFor1'),
+ anchorFor2: build('JsBlockOpen', 'JsGroupOpen', 'JsArrayOpen', 'JsSingleQuoteOpen', 'JsDoubleQuoteOpen', 'TextOpen', 'TagEnter', 'AnchorFor2'),
+ anchorWhile1: build('JsBlockOpen', 'JsGroupOpen', 'JsArrayOpen', 'JsSingleQuoteOpen', 'JsDoubleQuoteOpen', 'AnchorWhile1'),
+ anchorWhile2: build('JsBlockOpen', 'JsGroupOpen', 'JsArrayOpen', 'JsSingleQuoteOpen', 'JsDoubleQuoteOpen', 'TextOpen', 'TagEnter', 'AnchorWhile2'),
+ anchorDoWhile1: build('JsBlockOpen', 'JsGroupOpen', 'JsArrayOpen', 'JsSingleQuoteOpen', 'JsDoubleQuoteOpen', 'TextOpen', 'TagEnter', 'AnchorDoWhile1'),
+ anchorDoWhile2: build('JsBlockOpen', 'JsGroupOpen', 'JsArrayOpen', 'JsSingleQuoteOpen', 'JsDoubleQuoteOpen', 'AnchorDoWhile2'),
+ anchorSwitch1: build('JsBlockOpen', 'JsGroupOpen', 'JsArrayOpen', 'JsSingleQuoteOpen', 'JsDoubleQuoteOpen', 'AnchorSwitch1'),
+ anchorSwitch2: build('JsBlockOpen', 'JsGroupOpen', 'JsArrayOpen', 'JsSingleQuoteOpen', 'JsDoubleQuoteOpen', 'TextOpen', 'TagEnter', 'AnchorSwitch2'),
+ anchorWith1: build('JsBlockOpen', 'JsGroupOpen', 'JsArrayOpen', 'JsSingleQuoteOpen', 'JsDoubleQuoteOpen', 'AnchorWhith1'),
+ anchorWith2: build('JsBlockOpen', 'JsGroupOpen', 'JsArrayOpen', 'JsSingleQuoteOpen', 'JsDoubleQuoteOpen', 'TextOpen', 'TagEnter', 'AnchorWhith2'),
+ jsBlock: build('JsBlockClose', 'JsBlockOpen', 'JsGroupOpen', 'JsArrayOpen', 'JsSingleQuoteOpen', 'JsDoubleQuoteOpen', 'TextOpen', 'TagEnter'),
+ jsGroup: build('JsGroupClose', 'JsBlockOpen', 'JsGroupOpen', 'JsArrayOpen', 'JsSingleQuoteOpen', 'JsDoubleQuoteOpen'),
+ jsArray: build('JsArrayClose', 'JsBlockOpen', 'JsGroupOpen', 'JsArrayOpen', 'JsSingleQuoteOpen', 'JsDoubleQuoteOpen'),
+ jsMember: build('JsMemberOpen', 'JsBlockOpen', 'JsGroupOpen', 'JsArrayOpen', 'JsMemberClose'),
+ jsDoubleQuote: build('JsStringEscaped', 'JsDoubleQuoteClose'),
+ jsSingleQuote: build('JsStringEscaped', 'JsSingleQuoteClose')
+ };
+})();
+
+function create(parseCallback, bufferSize) {
+ function ontoken(token, buffer) {
+ if (token) {
+ var preceding = token.match?buffer.substr(0, token.match.index):'';
+ switch (token.category) {
+ case 'JsStringEscaped':
+ parseCallback(preceding + token.match[0]);
+ break;
+ case 'JsDoubleQuoteOpen':
+ parseCallback(preceding + token.match[0]);
+ this.pushRuleSet(rule.jsDoubleQuote);
+ break;
+ case 'JsDoubleQuoteClose':
+ parseCallback(preceding + token.match[0]);
+ this.popRuleSet();
+ break;
+ case 'JsSingleQuoteOpen':
+ parseCallback(preceding + token.match[0]);
+ this.pushRuleSet(rule.jsSingleQuote);
+ break;
+ case 'JsSingleQuoteClose':
+ parseCallback(preceding + token.match[0]);
+ this.popRuleSet();
+ break;
+ case 'JsGroupOpen':
+ parseCallback(preceding + token.match[0]);
+ this.pushRuleSet(rule.jsGroup);
+ break;
+ case 'JsGroupClose':
+ parseCallback(preceding + token.match[0]);
+ this.popRuleSet();
+ break;
+ case 'JsBlockOpen':
+ parseCallback(preceding + token.match[0]);
+ this.pushRuleSet(rule.jsBlock);
+ break;
+ case 'JsBlockClose':
+ parseCallback(preceding + token.match[0]);
+ this.popRuleSet();
+ break;
+ case 'JsArrayOpen':
+ parseCallback(preceding + token.match[0]);
+ this.pushRuleSet(rule.jsArray);
+ break;
+ case 'JsArrayClose':
+ parseCallback(preceding + token.match[0]);
+ this.popRuleSet();
+ break;
+ case 'JsMemberOpen':
+ parseCallback(token.match[0]);
+ this.pushRuleSet(rule.jsMember);
+ break;
+ case 'JsMemberClose':
+ this.popRuleSet();
+ break;
+ case 'AnchorEscaped':
+ parseCallback('stream.write(' + JSON.stringify(preceding + token.match[1]) + ');\n');
+ break;
+ case 'AnchorIfElse':
+ parseCallback('stream.write(' + JSON.stringify(preceding) + ');\n');
+ parseCallback('if(');
+ this.pushRuleSet(rule.anchorIfElse1);
+ break;
+ case 'AnchorIfElse1':
+ parseCallback(preceding);
+ parseCallback(') {\n');
+ this.popRuleSet();
+ this.pushRuleSet(rule.anchorIfElse2);
+ break;
+ case 'AnchorIfElse2':
+ parseCallback(preceding);
+ parseCallback('}\n');
+ this.popRuleSet();
+ if (token.match[1]) {
+ parseCallback('else {\n');
+ this.pushRuleSet(rule.anchorIfElse3);
+ }
+ break;
+ case 'AnchorIfElse3':
+ parseCallback(preceding);
+ parseCallback('}\n');
+ this.popRuleSet();
+ break;
+ case 'AnchorFor':
+ parseCallback('stream.write(' + JSON.stringify(preceding) + ');\n');
+ parseCallback('for(');
+ this.pushRuleSet(rule.anchorIfElse1);
+ break;
+ case 'AnchorFor1':
+ parseCallback(preceding);
+ parseCallback(') {\n');
+ this.popRuleSet();
+ this.pushRuleSet(rule.anchorIfElse2);
+ break;
+ case 'AnchorFor2':
+ parseCallback(preceding);
+ parseCallback('}\n');
+ this.popRuleSet();
+ break;
+ case 'AnchorWhile':
+ parseCallback('stream.write(' + JSON.stringify(preceding) + ');\n');
+ parseCallback('while(');
+ this.pushRuleSet(rule.anchorWhile1);
+ break;
+ case 'AnchorWhile1':
+ parseCallback(preceding);
+ parseCallback(') {\n');
+ this.popRuleSet();
+ this.pushRuleSet(rule.anchorWhile2);
+ break;
+ case 'AnchorWhile2':
+ parseCallback(preceding);
+ parseCallback('}\n');
+ this.popRuleSet();
+ break;
+ case 'AnchorDoWhile':
+ parseCallback('stream.write(' + JSON.stringify(preceding) + ');\n');
+ parseCallback('do {\n');
+ this.pushRuleSet(rule.anchorDoWhile1);
+ break;
+ case 'AnchorDoWhile1':
+ parseCallback(preceding);
+ parseCallback('} while(');
+ this.popRuleSet();
+ this.pushRuleSet(rule.anchorDoWhile2);
+ break;
+ case 'AnchorDoWhile2':
+ parseCallback(preceding);
+ parseCallback(');\n');
+ this.popRuleSet();
+ break;
+ case 'AnchorSwitch':
+ parseCallback('stream.write(' + JSON.stringify(preceding) + ');\n');
+ parseCallback('switch(');
+ this.pushRuleSet(rule.anchorWhile1);
+ break;
+ case 'AnchorSwitch1':
+ parseCallback(preceding);
+ parseCallback(') {\n');
+ this.popRuleSet();
+ this.pushRuleSet(rule.anchorWhile2);
+ break;
+ case 'AnchorSwitch2':
+ parseCallback(preceding);
+ parseCallback('}\n');
+ this.popRuleSet();
+ break;
+ case 'AnchorWith':
+ parseCallback('stream.write(' + JSON.stringify(preceding) + ');\n');
+ parseCallback('with(');
+ this.pushRuleSet(rule.anchorWhile1);
+ break;
+ case 'AnchorWith1':
+ parseCallback(preceding);
+ parseCallback(') {\n');
+ this.popRuleSet();
+ this.pushRuleSet(rule.anchorWhile2);
+ break;
+ case 'AnchorWith2':
+ parseCallback(preceding);
+ parseCallback('}\n');
+ this.popRuleSet();
+ break;
+ case 'AnchorGroupOpen':
+ parseCallback('stream.write(' + JSON.stringify(preceding) + ');\n');
+ parseCallback('stream.write(html.encode(');
+ this.pushRuleSet(rule.anchorGroup);
+ break;
+ case 'AnchorGroupClose':
+ parseCallback(preceding);
+ parseCallback('));\n');
+ this.popRuleSet();
+ break;
+ case 'AnchorBlockOpen':
+ parseCallback('stream.write(' + JSON.stringify(preceding) + ');\n');
+ this.pushRuleSet(rule.anchorBlock);
+ break;
+ case 'AnchorBlockClose':
+ parseCallback(preceding);
+ this.popRuleSet();
+ break;
+ case 'AnchorInlineOpen':
+ parseCallback('stream.write(' + JSON.stringify(preceding) + ');\n');
+ parseCallback('if(typeof ' + token.match[1] + ' == "undefined") stream.write(' + JSON.stringify(token.match[0]) + ');\n');
+ parseCallback('else stream.write(html.encode(' + token.match[1]);
+ this.pushRuleSet(rule.anchorInline);
+ break;
+ case 'AnchorInlineClose':
+ parseCallback('));\n');
+ this.popRuleSet();
+ break;
+
+ case 'TagRecurse':
+ parseCallback('stream.write(' + JSON.stringify(preceding + token.match[0]) + ');\n');
+ this.pushRuleSet(rule.tag);
+ this.pushRuleSet(rule.tagHead);
+ break;
+ case 'TagEnter':
+ parseCallback(preceding);
+ parseCallback('stream.write(' + JSON.stringify(token.match[0]) + ');\n');
+ this.pushRuleSet(rule.tag);
+ this.pushRuleSet(rule.tagHead);
+ break;
+ case 'TagExit':
+ parseCallback('stream.write(' + JSON.stringify(preceding + token.match[0]) + ');\n');
+ this.popRuleSet();
+ this.popRuleSet();
+ break;
+ case 'TagExitOpen':
+ parseCallback('stream.write(' + JSON.stringify(preceding + token.match[0]) + ');\n');
+ this.popRuleSet();
+ break;
+ case 'TagClose':
+ parseCallback('stream.write(' + JSON.stringify(preceding + token.match[0]) + ');\n');
+ this.popRuleSet();
+ break;
+ case 'TextOpen':
+ parseCallback(preceding);
+ this.pushRuleSet(rule.text);
+ break;
+ case 'TextClose':
+ parseCallback('stream.write(' + JSON.stringify(preceding) + ');\n');
+ this.popRuleSet();
+ break;
+ default:
+ throw 'unknown ' + token.category;
+ }
+ }
+ else {
+ parseCallback('stream.write(' + JSON.stringify(buffer) + ');\n');
+ }
+ }
+ var jsHtmlTokenizer = tokenizer.create(ontoken);
+ jsHtmlTokenizer.pushRuleSet(rule.root);
+ this.write = jsHtmlTokenizer.write;
+ this.flush = jsHtmlTokenizer.flush;
+ return this;
+}
+exports.create = create;
64 lib/tokenizer.js
@@ -0,0 +1,64 @@
+/*!
+ * tokenizer
+ * Copyright(c) 2011 Elmer Bulthuis <elmerbulthuis@gmail.com>
+ * MIT Licensed
+ */
+var assert = require('assert');
+
+function create(tokenCallback, bufferSize) {
+ var tokenizer = this;
+ var buffer = '';
+ bufferSize = bufferSize || 1024;
+ var ruleSetStack = [];
+
+ function pushRuleSet(ruleSet) {
+ ruleSetStack.unshift(ruleSet);
+ }
+
+ function popRuleSet() {
+ return ruleSetStack.shift();
+ }
+
+ function write(data) {
+ buffer += data;
+ while (buffer.length > bufferSize) {
+ process();
+ }
+ }
+
+ function flush() {
+ while (buffer.length > 0) {
+ process();
+ }
+ }
+
+ function getToken() {
+ var token = null;
+ var ruleSet = ruleSetStack[0];
+ assert.ok(ruleSet);
+ for (var category in ruleSet) {
+ var expression = ruleSet[category];
+ var match = expression.exec(buffer);
+ if (match && (!token || !token.match||match.index < token.match.index)) {
+ token = {
+ category: category,
+ match: match
+ };
+ }
+ }
+ return token;
+ }
+
+ function process() {
+ var token = getToken();
+ tokenCallback.call(tokenizer, token, buffer);
+ if (token &&token.match) buffer = buffer.substr(token.match.index + token.match[0].length);
+ else buffer = '';
+ }
+ tokenizer.write = write;
+ tokenizer.flush = flush;
+ tokenizer.pushRuleSet = pushRuleSet;
+ tokenizer.popRuleSet = popRuleSet;
+ return tokenizer;
+}
+exports.create = create;
0 main.js
No changes.
11 package.json
@@ -0,0 +1,11 @@
+{
+ "name": "jshtml",
+ "description": "razor template engine",
+ "version": "0.1.0",
+ "author": "Elmer Bulthuis <elmerbulthuis@gmail.com>",
+ "main": "main.js",
+ "scripts": {
+ "build": "build.js",
+ "test": "test.js"
+ },
+}
23 test.js
@@ -0,0 +1,23 @@
+function run(module) {
+ console.log(module);
+ var testSet = require(module).testSet;
+ var testIndex = 0;
+ for (var testName in testSet) {
+ var test = testSet[testName];
+ var info = [];
+ info[0] = testName;
+ var offset = new Date().getTime();
+ try {
+ test();
+ info[2] = 'OK';
+ }
+ catch (err) {
+ info[2] = err;
+ }
+ info[1] = (new Date().getTime() - offset) + 'ms';
+ console.log((testIndex + 1) + ') ' + info.join(' - '));
+ testIndex++;
+ }
+}
+run('./test/compile');
+run('./test/render');
24 test/compile.js
@@ -0,0 +1,24 @@
+var assert = require('assert');
+var fs = require('fs');
+var parser = require('../lib/jsHtmlParser');
+var html = require('../lib/html');
+exports.testSet = {};
+fs.readdirSync(__dirname).forEach(function(file) {
+ var match = /(.+)\.jshtml$/i.exec(file);
+ if (!match) return;
+ exports.testSet[match[1]] = function() {
+ var body = '';
+ var p = parser.create(function(str) {
+ body += str;
+ });
+ p.write(fs.readFileSync(__dirname + '/' + match[0], 'utf8'));
+ p.flush();
+ try {
+ new Function(body);
+ }
+ catch (e) {
+ console.log(html.encode(body));
+ throw e;
+ }
+ };
+});
14 test/dowhile.jshtml
@@ -0,0 +1,14 @@
+<html>
+<head>
+ <title>Test</title>
+</head>
+
+<body>
+@{var n = 10;}
+@do {
+ <p>
+@n
+ </p>
+ } while( --n > 0)
+</body>
+</html>
13 test/for.jshtml
@@ -0,0 +1,13 @@
+<html>
+<head>
+ <title>Test</title>
+</head>
+
+<body>
+@for(var n = 1; n <= 10; n++ ) {
+ <p>
+@n
+ </p>
+ }
+</body>
+</html>
14 test/forin.jshtml
@@ -0,0 +1,14 @@
+<html>
+<head>
+ <title>Test</title>
+</head>
+
+<body>
+@{var n = {one:'een', two:'twee', three:'drie'};}
+@for(var key in n) {
+ <text>
+@key=@n[key]<br />
+ </text>
+ }
+</body>
+</html>
13 test/if.jshtml
@@ -0,0 +1,13 @@
+<html>
+<head>
+ <title>Test</title>
+</head>
+
+<body>
+@if(stoer && lief) {
+ <p>
+Yeah!
+ </p>
+ }
+</body>
+</html>
19 test/ifelse.jshtml
@@ -0,0 +1,19 @@
+<html>
+<head>
+ <title>Test</title>
+</head>
+<body>
+
+@if(stoer && lief) {
+ <text>
+Yeah!
+ </text>
+ }
+else {
+ <text>
+Ahhhhh...
+ </text>
+ }
+
+</body>
+</html
45 test/productTable.jshtml
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>@title</title>
+</head>
+
+<body>
+<div id="wrapper">
+
+<header>
+</header>
+
+<section>
+@if(productList && productList.length) {
+ <table>
+ <thead>
+ <tr>
+ <th>Name</th>
+ <th>Price</th>
+ </tr>
+ </thead>
+ <tbody>
+ @for(var productIndex = 0; productIndex < productList.length; productIndex++) {
+ var product = productList[productIndex]
+ <tr>
+ <td>@(product.name)</td>
+ <td>@(product.price)</td>
+ </tr>
+ }
+ </tbody>
+ </table>
+ }
+else{
+ <p>
+ no products found...
+ </p>
+ }
+</section>
+
+<footer>
+</footer>
+
+</div>
+</body>
+</html>
51 test/render.js
@@ -0,0 +1,51 @@
+var assert = require('assert');
+var fs = require('fs');
+var parser = require('../lib/jsHtmlParser');
+var html = require('../lib/html');
+exports.testSet = {};
+fs.readdirSync(__dirname).forEach(function(file) {
+ var match = /(.+)\.jshtml$/i.exec(file);
+ if (!match) return;
+ exports.testSet[match[1]] = function() {
+ var body = '';
+ var p = parser.create(function(str) {
+ body += str;
+ });
+ p.write(fs.readFileSync(__dirname + '/' + match[0], 'utf8'));
+ p.flush();
+ var fn = new Function('stream', 'html', 'locals', 'with(locals) {\n ' + body + '}\n');
+ var content = '';
+ fn({
+ write: function(str) {
+ content += str;
+ }
+ }, html, {
+ stoer: true,
+ lief: true,
+ taskList: [{
+ id: 1,
+ name: 'build a house'
+ }, {
+ id: 2,
+ name: 'run a marathon'
+ }, {
+ id: 3,
+ name: 'grow a beard'
+ }],
+ productList: [{
+ id: 1,
+ name: 'Blend',
+ price: 9.5
+ }, {
+ id: 1,
+ name: 'I LOVE FAKE',
+ price: 12.5
+ }, {
+ id: 1,
+ name: 'Gup',
+ price: 19.5
+ }]
+ });
+ //console.log(html.encode(content));
+ };
+});
28 test/switch.jshtml
@@ -0,0 +1,28 @@
+<html>
+<head>
+ <title>Test</title>
+</head>
+<body>
+
+@{var direction = 'other';}
+@switch(direction) {
+ case 'links':
+ <text>
+Left <-
+ </text>
+ break;
+
+ case 'rechts':
+ <text>
+-> Right
+ </text>
+ break;
+
+ default:
+ <text>
+Iets anders
+ </text>
+ }
+
+</body>
+</html
16 test/tags.jshtml
@@ -0,0 +1,16 @@
+@html.tag('html')
+
+@html.tag('head')
+@html.tag('title')
+@html.tag(true)
+@html.tag(true)
+
+@html.tag('body')
+
+@html.tag('p')
+@html.tag('a', {href:'http://luvdasun.com', target:'_blank'}, 'linkje')
+@html.tag(true)
+
+@html.tag(true)
+
+@html.tag(true)
17 test/taskList.jshtml
@@ -0,0 +1,17 @@
+<html>
+<head>
+ <title>@title()</title>
+</head>
+
+<body class="@body.class.xyz().abc">
+
+<ul class="Task">
+@{
+taskList.forEach(function(task,index) {
+ <li class="@(index % 2 ? "Odd" : "Even")">@task.name</li>
+ });
+}
+</ul>
+
+</body>
+</html>
55 test/text.jshtml
@@ -0,0 +1,55 @@
+<html>
+<head>
+ <title>Test</title>
+</head>
+
+<body>
+@{
+ var tagMode = 'tag-mode';
+
+ <p>@tagMode</p>
+
+ var textMode = 'text-mode';
+ <text>
+ @textMode
+ @{
+ var mode;
+ mode = tagMode;
+
+ <p>
+ @mode
+ @{
+ var message;
+ message = 'in textmode';
+
+ <text>
+ <p>
+ @message
+ </text>
+
+ message = 'we don\'t have to balance our tags!!!';
+
+ <text>
+ @message
+ </p>
+ </text>
+
+ <b><a><l><a><n><c><e>
+in tag-mode we do have to balance our tags!<br />
+however, the tag-types do not have to match.<br />
+ </b></a></l></a></n></c></e>
+ }
+ </p>
+
+ mode = textMode;
+
+ <text>
+ @mode
+ </text>
+ }
+ </text>
+ }
+
+
+</body>
+</html>
15 test/while.jshtml
@@ -0,0 +1,15 @@
+<html>
+<head>
+ <title>Test</title>
+</head>
+
+<body>
+@{var n = 10;}
+@while(n > 0) {
+ <p>
+@n
+ </p>
+n--;
+ }
+</body>
+</html>
19 test/with.jshtml
@@ -0,0 +1,19 @@
+<html>
+<head>
+ <title>Test</title>
+</head>
+
+<body>
+@with({one:'een', two:'twee', three:'drie'}) {
+ <p>
+@one
+ </p>
+ <p>
+@two
+ </p>
+ <p>
+@three
+ </p>
+ }
+</body>
+</html>

0 comments on commit 2e2d4c1

Please sign in to comment.
Something went wrong with that request. Please try again.