mirror of
https://github.com/marko-js/marko.git
synced 2025-12-08 19:26:05 +00:00
302 lines
8.2 KiB
JavaScript
302 lines
8.2 KiB
JavaScript
'use strict';
|
|
var isArray = Array.isArray;
|
|
|
|
var Node = require('./ast/Node');
|
|
var Program = require('./ast/Program');
|
|
var TemplateRoot = require('./ast/TemplateRoot');
|
|
var FunctionDeclaration = require('./ast/FunctionDeclaration');
|
|
var FunctionCall = require('./ast/FunctionCall');
|
|
var Literal = require('./ast/Literal');
|
|
var Identifier = require('./ast/Identifier');
|
|
var If = require('./ast/If');
|
|
var ElseIf = require('./ast/ElseIf');
|
|
var Else = require('./ast/Else');
|
|
var Assignment = require('./ast/Assignment');
|
|
var BinaryExpression = require('./ast/BinaryExpression');
|
|
var Vars = require('./ast/Vars');
|
|
var Return = require('./ast/Return');
|
|
var HtmlElement = require('./ast/HtmlElement');
|
|
var Html = require('./ast/Html');
|
|
var Text = require('./ast/Text');
|
|
var ForEach = require('./ast/ForEach');
|
|
var ForEachProp = require('./ast/ForEachProp');
|
|
var ForRange = require('./ast/ForRange');
|
|
var Slot = require('./ast/Slot');
|
|
var HtmlComment = require('./ast/HtmlComment');
|
|
var SelfInvokingFunction = require('./ast/SelfInvokingFunction');
|
|
var ForStatement = require('./ast/ForStatement');
|
|
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) {
|
|
if (typeof arg === 'string') {
|
|
return parseExpression(arg);
|
|
} else if (arg instanceof Node) {
|
|
return arg;
|
|
} else {
|
|
return undefined;
|
|
}
|
|
}
|
|
|
|
class Builder {
|
|
assignment(left, right, operator) {
|
|
if (operator == null) {
|
|
operator = '=';
|
|
}
|
|
left = makeNode(left);
|
|
right = makeNode(right);
|
|
return new Assignment({left, right, operator});
|
|
}
|
|
|
|
binaryExpression(left, operator, right) {
|
|
left = makeNode(left);
|
|
right = makeNode(right);
|
|
return new BinaryExpression({left, operator, right});
|
|
}
|
|
|
|
code(value) {
|
|
return new Code({value});
|
|
}
|
|
|
|
elseStatement(body) {
|
|
return new Else({body});
|
|
}
|
|
|
|
elseIfStatement(test, body, elseStatement) {
|
|
test = makeNode(test);
|
|
|
|
return new ElseIf({test, body, else: elseStatement});
|
|
}
|
|
|
|
expression(value) {
|
|
return makeNode(value);
|
|
}
|
|
|
|
forEach(varName, inExpression, body) {
|
|
if (arguments.length === 1) {
|
|
var def = arguments[0];
|
|
return new ForEach(def);
|
|
} else {
|
|
varName = makeNode(varName);
|
|
inExpression = makeNode(inExpression);
|
|
return new ForEach({varName, in: inExpression, body});
|
|
}
|
|
}
|
|
|
|
forEachProp(nameVarName, valueVarName, inExpression, body) {
|
|
if (arguments.length === 1) {
|
|
var def = arguments[0];
|
|
return new ForEachProp(def);
|
|
} else {
|
|
nameVarName = makeNode(nameVarName);
|
|
valueVarName = makeNode(valueVarName);
|
|
inExpression = makeNode(inExpression);
|
|
return new ForEachProp({nameVarName, valueVarName, in: inExpression, body});
|
|
}
|
|
}
|
|
|
|
forRange(varName, from, to, step, body) {
|
|
if (arguments.length === 1) {
|
|
var def = arguments[0];
|
|
return new ForRange(def);
|
|
} else {
|
|
varName = makeNode(varName);
|
|
from = makeNode(from);
|
|
to = makeNode(to);
|
|
step = makeNode(step);
|
|
body = makeNode(body);
|
|
|
|
return new ForRange({varName, from, to, step, body});
|
|
}
|
|
}
|
|
|
|
forStatement(init, test, update, body) {
|
|
if (arguments.length === 1) {
|
|
var def = arguments[0];
|
|
return new ForStatement(def);
|
|
} else {
|
|
init = makeNode(init);
|
|
test = makeNode(test);
|
|
update = makeNode(update);
|
|
return new ForStatement({init, test, update, body});
|
|
}
|
|
}
|
|
|
|
functionCall(callee, args) {
|
|
callee = makeNode(callee);
|
|
|
|
if (args) {
|
|
if (!isArray(args)) {
|
|
args = [args];
|
|
}
|
|
|
|
for (var i=0; i<args.length; i++) {
|
|
args[i] = makeNode(args[i]);
|
|
}
|
|
} else {
|
|
args = [];
|
|
}
|
|
|
|
return new FunctionCall({callee, args});
|
|
}
|
|
|
|
functionDeclaration(name, params, body) {
|
|
return new FunctionDeclaration({name, params, body});
|
|
}
|
|
|
|
html(argument) {
|
|
argument = makeNode(argument);
|
|
|
|
return new Html({argument});
|
|
}
|
|
|
|
htmlComment(comment) {
|
|
return new HtmlComment({comment});
|
|
}
|
|
|
|
htmlElement(tagName, attributes, body, argument) {
|
|
if (typeof tagName === 'object' && !(tagName instanceof Node)) {
|
|
let def = arguments[0];
|
|
return new HtmlElement(def);
|
|
} else {
|
|
return new HtmlElement({tagName, attributes, body, argument});
|
|
}
|
|
}
|
|
|
|
identifier(name) {
|
|
return new Identifier({name});
|
|
}
|
|
|
|
ifStatement(test, body, elseStatement) {
|
|
return new If({test, body, else: elseStatement});
|
|
}
|
|
|
|
literal(value) {
|
|
return new Literal({value});
|
|
}
|
|
|
|
memberExpression(object, property, computed) {
|
|
object = makeNode(object);
|
|
property = makeNode(property);
|
|
|
|
return new MemberExpression({object, property, computed});
|
|
}
|
|
|
|
negate(argument) {
|
|
argument = makeNode(argument);
|
|
|
|
var operator = '!';
|
|
var prefix = true;
|
|
return new UnaryExpression({argument, operator, prefix});
|
|
}
|
|
|
|
node(type, generateCode) {
|
|
if (typeof type === 'function') {
|
|
generateCode = arguments[0];
|
|
type = 'Node';
|
|
}
|
|
|
|
var node = new Node(type);
|
|
if (generateCode) {
|
|
node.setCodeGenerator(generateCode);
|
|
}
|
|
return node;
|
|
}
|
|
|
|
program(body) {
|
|
return new Program({body});
|
|
}
|
|
|
|
require(path) {
|
|
path = makeNode(path);
|
|
|
|
let callee = 'require';
|
|
let args = [ path ];
|
|
return new FunctionCall({callee, args});
|
|
}
|
|
|
|
returnStatement(argument) {
|
|
argument = makeNode(argument);
|
|
|
|
return new Return({argument});
|
|
}
|
|
|
|
selfInvokingFunction(params, args, body) {
|
|
if (arguments.length === 1) {
|
|
body = arguments[0];
|
|
params = null;
|
|
args = null;
|
|
}
|
|
|
|
return new SelfInvokingFunction({params, args, body});
|
|
}
|
|
|
|
slot(onDone) {
|
|
return new Slot({onDone});
|
|
}
|
|
|
|
strictEquality(left, right) {
|
|
left = makeNode(left);
|
|
right = makeNode(right);
|
|
|
|
var operator = '===';
|
|
return new BinaryExpression({left, right, operator});
|
|
}
|
|
|
|
templateRoot(body) {
|
|
return new TemplateRoot({body});
|
|
}
|
|
|
|
text(argument, escape) {
|
|
argument = makeNode(argument);
|
|
|
|
return new Text({argument, escape});
|
|
}
|
|
|
|
unaryExpression(argument, operator, prefix) {
|
|
argument = makeNode(argument);
|
|
|
|
return new UnaryExpression({argument, operator, prefix});
|
|
}
|
|
|
|
updateExpression(argument, operator, prefix) {
|
|
argument = makeNode(argument);
|
|
return new UpdateExpression({argument, operator, prefix});
|
|
}
|
|
|
|
vars(declarations, kind) {
|
|
if (declarations) {
|
|
if (Array.isArray(declarations)) {
|
|
for (let i=0; i<declarations.length; i++) {
|
|
var declaration = declarations[i];
|
|
if (typeof declaration === 'string') {
|
|
declarations[i] = {
|
|
id: makeNode(declaration)
|
|
};
|
|
} else if (declaration instanceof Identifier) {
|
|
declarations[i] = {
|
|
id: declaration
|
|
};
|
|
}
|
|
}
|
|
} else if (typeof declarations === 'object') {
|
|
// Convert the object into an array of variables
|
|
declarations = Object.keys(declarations).map((key) => {
|
|
let id = new Identifier({name: key});
|
|
let init = makeNode(declarations[key]);
|
|
return { id, init };
|
|
});
|
|
}
|
|
}
|
|
|
|
|
|
return new Vars({declarations, kind});
|
|
}
|
|
}
|
|
|
|
module.exports = Builder; |