Fixes #195 <template-init> added

This commit is contained in:
Patrick Steele-Idem 2015-12-30 19:57:15 -07:00
parent 4557d307b0
commit 6153b13959
13 changed files with 163 additions and 61 deletions

View File

@ -29,6 +29,8 @@ var BinaryExpression = require('./ast/BinaryExpression');
var UpdateExpression = require('./ast/UpdateExpression');
var UnaryExpression = require('./ast/UnaryExpression');
var MemberExpression = require('./ast/MemberExpression');
var Code = require('./ast/Code');
var parseExpression = require('./util/parseExpression');
function makeNode(arg) {
@ -57,6 +59,10 @@ class Builder {
return new BinaryExpression({left, operator, right});
}
code(value) {
return new Code({value});
}
elseStatement(body) {
return new Else({body});
}

View File

@ -20,7 +20,7 @@ class Slot {
}
this._end = codegen._code.length;
this._currentIndent = codegen._currentIndent;
this.currentIndent = codegen.currentIndent;
this._inFunction = codegen.inFunction;
this._statement = slotNode.statement;
}
@ -36,24 +36,26 @@ class Slot {
if (content) {
let isStatement = this._statement;
codegen._currentIndent = this._currentIndent;
codegen.currentIndent = this.currentIndent;
codegen.inFunction = this._inFunction;
let capture = codegen._beginCaptureCode();
if (isArray(content) || (content instanceof Container)) {
content.forEach((node) => {
node.statement = isStatement;
codegen.generateCode(node);
});
if (isStatement) {
codegen.generateStatements(content);
} else {
content.statement = isStatement;
codegen.generateCode(content);
}
slotCode = capture.end();
if (isStatement && slotCode.startsWith(codegen.currentIndent)) {
slotCode = slotCode.substring(codegen.currentIndent.length);
}
}
let oldCode = codegen._code;
let beforeCode = oldCode.substring(0, this._start);
let afterCode = oldCode.substring(this._end);
@ -70,7 +72,7 @@ class Generator {
this._indentSize = this._indentStr.length;
this._code = '';
this._currentIndent = '';
this.currentIndent = '';
this.inFunction = false;
this._doneListeners = [];
@ -103,10 +105,18 @@ class Generator {
return this.context.addStaticVar(name, value);
}
addStaticCode(code) {
this.context.addStaticCode(code);
}
getStaticVars() {
return this.context.getStaticVars();
}
getStaticCode() {
return this.context.getStaticCode();
}
generateCode(node) {
ok(node != null, '"node" is required');
@ -266,7 +276,7 @@ class Generator {
let startCodeLen = this._code.length;
let currentIndent = this._currentIndent;
let currentIndent = this.currentIndent;
if (!firstStatement) {
this._write('\n');
@ -286,7 +296,11 @@ class Generator {
return;
}
if (!this._code.endsWith('\n')) {
if (this._code.endsWith('\n')) {
// Do nothing
} else if (this._code.endsWith(';')) {
this._code += '\n';
} else {
this._code += ';\n';
}
@ -354,7 +368,7 @@ class Generator {
this._bufferedWrites = null;
if (!addSeparator && !this._code.endsWith(this._currentIndent)) {
if (!addSeparator && !this._code.endsWith(this.currentIndent)) {
this.writeLineIndent();
}
@ -377,7 +391,7 @@ class Generator {
this._write(');\n');
if (addSeparator) {
this._write('\n' + this._currentIndent);
this._write('\n' + this.currentIndent);
}
}
@ -397,10 +411,10 @@ class Generator {
incIndent(count) {
if (count != null) {
for (let i=0; i<count; i++) {
this._currentIndent += ' ';
this.currentIndent += ' ';
}
} else {
this._currentIndent += this._indentStr;
this.currentIndent += this._indentStr;
}
return this;
@ -411,15 +425,15 @@ class Generator {
count = this._indentSize;
}
this._currentIndent = this._currentIndent.substring(
this.currentIndent = this.currentIndent.substring(
0,
this._currentIndent.length - count);
this.currentIndent.length - count);
return this;
}
writeLineIndent() {
this._code += this._currentIndent;
this._code += this.currentIndent;
return this;
}

View File

@ -33,6 +33,7 @@ class CompileContext {
this.data = {};
this._staticVars = {};
this._staticCode = null;
this._uniqueVars = new UniqueVars();
this._srcCharProps = null;
this._flags = {};
@ -84,6 +85,22 @@ class CompileContext {
return this._staticVars;
}
addStaticCode(code) {
if (!code) {
return;
}
if (this._staticCode == null) {
this._staticCode = [code];
} else {
this._staticCode.push(code);
}
}
getStaticCode() {
return this._staticCode;
}
createNodeForEl(tagName, attributes, argument) {
var elDef;
var builder = this.builder;
@ -174,6 +191,8 @@ class CompileContext {
}
}
});
node.tagDef = tagDef;
}
return node;

View File

@ -3,8 +3,7 @@ var htmljs = require('htmljs-parser');
class HtmlJsParser {
parse(src, handlers) {
var parser = htmljs.createParser({
var parser = this.parser = htmljs.createParser({
ontext(event) {
handlers.handleCharacters(event.text);
},
@ -57,6 +56,14 @@ class HtmlJsParser {
parser.parse(src);
}
enterParsedTextContentState() {
this.parser.enterParsedTextContentState();
}
enterStaticTextContentState() {
this.parser.enterStaticTextContentState();
}
}
module.exports = HtmlJsParser;

View File

@ -132,6 +132,18 @@ class Parser {
var node = this.context.createNodeForEl(elDef);
var tagDef = node.tagDef;
if (node.tagDef) {
var body = tagDef.body;
if (body) {
if (body === 'parsed-text') {
this.parserImpl.enterParsedTextContentState();
} else if (body === 'static-text') {
this.parserImpl.enterStaticTextContentState();
}
}
}
this.parentNode.appendChild(node);
this.stack.push({

25
compiler/ast/Code.js Normal file
View File

@ -0,0 +1,25 @@
'use strict';
var Node = require('./Node');
var adjustIndent = require('../util/adjustIndent');
class Code extends Node {
constructor(def) {
super('Code');
this.value = def.value;
}
generateCode(codegen) {
var code = this.value;
if (!code) {
return;
}
code = adjustIndent(code, codegen.currentIndent);
codegen.write(code);
}
}
module.exports = Code;

View File

@ -11,6 +11,7 @@ class Node {
this.statement = false;
this.container = null;
this.pos = null; // The character index of the node in the original source file
this.tagDef = null; // The tag definition associated with this Node
this._codeGeneratorFuncs = null;
this._flags = {};
this._transformersApplied = {};
@ -77,6 +78,7 @@ class Node {
delete result._codeGeneratorFuncs;
delete result._flags;
delete result.data;
delete result.tagDef;
return result;
}
@ -143,6 +145,21 @@ class Node {
return this._flags.hasOwnProperty(name);
}
get bodyText() {
var bodyText = '';
this.forEachChild((child) => {
if (child.type === 'Text') {
var childText = child.argument;
if (childText && childText.type === 'Literal') {
bodyText += childText.value;
}
}
});
return bodyText;
}
get parentNode() {
return this.container && this.container.node;
}

View File

@ -46,10 +46,16 @@ class TemplateRoot extends Node {
codegen.generateCode(outputNode);
var staticVars = codegen.getStaticVars();
var staticCodeArray = codegen.getStaticCode();
staticsSlot.setContent([
vars(createVarsArray(staticVars))
]);
var staticContent = [vars(createVarsArray(staticVars))];
if (staticCodeArray) {
staticCodeArray.forEach((code) => {
staticContent.push(builder.code(code));
});
}
staticsSlot.setContent(staticContent);
}
toJSON(prettyPrinter) {

View File

@ -50,6 +50,7 @@ class Tag{
this.isRepeated = null;
this.isNestedTag = false;
this.parentTagName = null;
this.body = null;
this.type = null; // Only applicable for nested tags
this._nodeFactory = undefined;
}

View File

@ -413,6 +413,18 @@ TagHandlers.prototype = {
if (value === false) {
this.tag.escapeXmlBody = false;
}
},
/**
* Sends the body content type. This is used to control how the body
* content is parsed.
*/
body: function(value) {
if (value === 'static-text' || value === 'parsed-text' || value === 'html') {
this.tag.body = value;
} else {
throw new Error('Invalid value for "body". Allowed: "static-text", "parsed-text" or "html"');
}
}
};

View File

@ -1,15 +1,19 @@
{
"<else>": {
"node-factory": "./else-tag"
},
"<else-if>": {
"node-factory": "./else-if-tag"
},
"<for>": {
"code-generator": "./for-tag"
},
"<if>": {
"node-factory": "./if-tag"
},
"<else-if>": {
"node-factory": "./else-if-tag"
},
"<else>": {
"node-factory": "./else-tag"
"<template-init>": {
"code-generator": "./template-init-tag",
"body": "static-text"
},
"<var>": {
"node-factory": "./var-tag"

View File

@ -0,0 +1,6 @@
module.exports = function codeGenerator(elNode, codegen) {
var bodyText = elNode.bodyText;
codegen.addStaticCode(bodyText);
};

View File

@ -2,41 +2,14 @@ function create(__helpers) {
var str = __helpers.s,
empty = __helpers.e,
notEmpty = __helpers.ne,
escapeXml = __helpers.x,
forEach = __helpers.f;
escapeXml = __helpers.x;
var name = 'Frank';
return function render(data, out) {
out.w("Hello " +
escapeXml(data.name) +
"! ");
if (notEmpty(data.colors)) {
out.w("<ul>");
forEach(data.colors, function(color) {
out.w("<li>" +
escapeXml(color) +
"</li>");
});
out.w("</ul>");
} else {
out.w("<div>No colors!</div>");
}
if (notEmpty(data.colors)) {
out.w("<ul>");
forEach(data.colors, function(color) {
out.w("<li>" +
escapeXml(color) +
"</li>");
});
out.w("</ul>");
} else {
out.w("<div>No colors!</div>");
}
out.w(" Hello " +
escapeXml(name) +
"!");
};
}