mirror of
https://github.com/marko-js/marko.git
synced 2025-12-08 19:26:05 +00:00
Fixes #195 <template-init> added
This commit is contained in:
parent
4557d307b0
commit
6153b13959
@ -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});
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
@ -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
25
compiler/ast/Code.js
Normal 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;
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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"');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -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"
|
||||
|
||||
6
taglibs/core/template-init-tag.js
Normal file
6
taglibs/core/template-init-tag.js
Normal file
@ -0,0 +1,6 @@
|
||||
|
||||
|
||||
module.exports = function codeGenerator(elNode, codegen) {
|
||||
var bodyText = elNode.bodyText;
|
||||
codegen.addStaticCode(bodyText);
|
||||
};
|
||||
@ -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) +
|
||||
"!");
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user