mirror of
https://github.com/marko-js/marko.git
synced 2025-12-08 19:26:05 +00:00
Restored range looping functionality
This commit is contained in:
parent
a9fd496589
commit
4b38989892
@ -1,6 +1,5 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
var isArray = Array.isArray;
|
var isArray = Array.isArray;
|
||||||
var ok = require('assert').ok;
|
|
||||||
|
|
||||||
var Program = require('./ast/Program');
|
var Program = require('./ast/Program');
|
||||||
var TemplateRoot = require('./ast/TemplateRoot');
|
var TemplateRoot = require('./ast/TemplateRoot');
|
||||||
@ -21,6 +20,8 @@ var TextOutput = require('./ast/TextOutput');
|
|||||||
var ForEach = require('./ast/ForEach');
|
var ForEach = require('./ast/ForEach');
|
||||||
var Slot = require('./ast/Slot');
|
var Slot = require('./ast/Slot');
|
||||||
var HtmlComment = require('./ast/HtmlComment');
|
var HtmlComment = require('./ast/HtmlComment');
|
||||||
|
var SelfInvokingFunction = require('./ast/SelfInvokingFunction');
|
||||||
|
var ForStatement = require('./ast/ForStatement');
|
||||||
|
|
||||||
class Builder {
|
class Builder {
|
||||||
program(body) {
|
program(body) {
|
||||||
@ -47,6 +48,16 @@ class Builder {
|
|||||||
return new FunctionCall({callee, args});
|
return new FunctionCall({callee, args});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
selfInvokingFunction(params, args, body) {
|
||||||
|
if (arguments.length === 1) {
|
||||||
|
body = arguments[0];
|
||||||
|
params = null;
|
||||||
|
args = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new SelfInvokingFunction({params, args, body});
|
||||||
|
}
|
||||||
|
|
||||||
literal(value) {
|
literal(value) {
|
||||||
return new Literal({value});
|
return new Literal({value});
|
||||||
}
|
}
|
||||||
@ -128,6 +139,15 @@ class Builder {
|
|||||||
let args = [ path ];
|
let args = [ path ];
|
||||||
return new FunctionCall({callee, args});
|
return new FunctionCall({callee, args});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
forStatement(init, test, update, body) {
|
||||||
|
if (typeof init === 'object' && !init.type) {
|
||||||
|
var def = arguments[0];
|
||||||
|
return new ForStatement(def);
|
||||||
|
} else {
|
||||||
|
return new ForStatement({init, test, update, body});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = Builder;
|
module.exports = Builder;
|
||||||
@ -26,15 +26,28 @@ class Slot {
|
|||||||
}
|
}
|
||||||
|
|
||||||
generateCode(generator) {
|
generateCode(generator) {
|
||||||
if (!this._content) {
|
var content = this._content;
|
||||||
|
|
||||||
|
if (!content) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var isStatement = this._statement;
|
||||||
|
|
||||||
generator._currentIndent = this._currentIndent;
|
generator._currentIndent = this._currentIndent;
|
||||||
generator.inFunction = this._inFunction;
|
generator.inFunction = this._inFunction;
|
||||||
|
|
||||||
var capture = generator._beginCaptureCode();
|
var capture = generator._beginCaptureCode();
|
||||||
generator.generateCode(this._content);
|
|
||||||
|
if (isArray(content) || (content instanceof Container)) {
|
||||||
|
content.forEach((node) => {
|
||||||
|
node.statement = isStatement;
|
||||||
|
generator.generateCode(node);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
content.statement = isStatement;
|
||||||
|
generator.generateCode(content);
|
||||||
|
}
|
||||||
|
|
||||||
var slotCode = capture.end();
|
var slotCode = capture.end();
|
||||||
|
|
||||||
@ -96,9 +109,11 @@ class Generator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
generateCode(node) {
|
generateCode(node) {
|
||||||
ok(node, '"node" is required');
|
ok(node != null, '"node" is required');
|
||||||
|
|
||||||
if (typeof node === 'string') {
|
if (typeof node === 'string' ||
|
||||||
|
typeof node === 'number' ||
|
||||||
|
typeof node === 'boolean') {
|
||||||
this.write(node);
|
this.write(node);
|
||||||
return;
|
return;
|
||||||
} else if (isArray(node) || (node instanceof Container)) {
|
} else if (isArray(node) || (node instanceof Container)) {
|
||||||
|
|||||||
@ -15,7 +15,7 @@ class ForEach extends Node {
|
|||||||
this.step = def.step;
|
this.step = def.step;
|
||||||
|
|
||||||
ok(this.varName, '"varName" is required');
|
ok(this.varName, '"varName" is required');
|
||||||
ok(this.target, '"target" is required');
|
ok(this.target != null || this.from != null, '"target" or "from" is required');
|
||||||
}
|
}
|
||||||
|
|
||||||
generateCode(generator) {
|
generateCode(generator) {
|
||||||
@ -26,9 +26,9 @@ class ForEach extends Node {
|
|||||||
|
|
||||||
var builder = generator.builder;
|
var builder = generator.builder;
|
||||||
|
|
||||||
if (this.from) {
|
if (this.from != null) {
|
||||||
// This is a range loop
|
// This is a range loop
|
||||||
var from = This.from;
|
var from = this.from;
|
||||||
var to = this.to;
|
var to = this.to;
|
||||||
var step = this.step;
|
var step = this.step;
|
||||||
var comparison = '<=';
|
var comparison = '<=';
|
||||||
@ -54,12 +54,16 @@ class ForEach extends Node {
|
|||||||
step = varName + '+=' + step;
|
step = varName + '+=' + step;
|
||||||
}
|
}
|
||||||
|
|
||||||
// template.statement('(function() {').indent(function () {
|
return builder.selfInvokingFunction([
|
||||||
// template.statement('for (var ' + nameVar + '=' + from + '; ' + nameVar + comparison + to + '; ' + step + ') {').indent(function () {
|
builder.forStatement({
|
||||||
// this.generateCodeForChildren(template);
|
init: [
|
||||||
// }, this).line('}');
|
builder.vars([ { id: varName, init: from }])
|
||||||
// }, this).line('}());');
|
],
|
||||||
return;
|
test: varName + comparison + to,
|
||||||
|
update: step,
|
||||||
|
body: this.body
|
||||||
|
})
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (separator && !statusVarName) {
|
if (separator && !statusVarName) {
|
||||||
|
|||||||
46
compiler/ast/ForStatement.js
Normal file
46
compiler/ast/ForStatement.js
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var Node = require('./Node');
|
||||||
|
|
||||||
|
class ForStatement extends Node {
|
||||||
|
constructor(def) {
|
||||||
|
super('ForStatement');
|
||||||
|
this.init = def.init;
|
||||||
|
this.test = def.test;
|
||||||
|
this.update = def.update;
|
||||||
|
this.body = this.makeContainer(def.body);
|
||||||
|
}
|
||||||
|
|
||||||
|
generateCode(generator) {
|
||||||
|
var init = this.init;
|
||||||
|
var test = this.test;
|
||||||
|
var update = this.update;
|
||||||
|
var body = this.body;
|
||||||
|
|
||||||
|
generator.write('for (');
|
||||||
|
|
||||||
|
if (init) {
|
||||||
|
generator.generateCode(init);
|
||||||
|
}
|
||||||
|
|
||||||
|
generator.write('; ');
|
||||||
|
|
||||||
|
if (test) {
|
||||||
|
generator.generateCode(test);
|
||||||
|
}
|
||||||
|
|
||||||
|
generator.write('; ');
|
||||||
|
|
||||||
|
if (update) {
|
||||||
|
generator.generateCode(update);
|
||||||
|
}
|
||||||
|
|
||||||
|
generator.write(') ');
|
||||||
|
|
||||||
|
generator.generateBlock(body);
|
||||||
|
|
||||||
|
generator.write('\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = ForStatement;
|
||||||
32
compiler/ast/SelfInvokingFunction.js
Normal file
32
compiler/ast/SelfInvokingFunction.js
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var Node = require('./Node');
|
||||||
|
|
||||||
|
class SelfInvokingFunction extends Node {
|
||||||
|
constructor(def) {
|
||||||
|
super('SelfInvokingFunction');
|
||||||
|
this.params = def.params;
|
||||||
|
this.args = def.args;
|
||||||
|
this.body = this.makeContainer(def.body);
|
||||||
|
}
|
||||||
|
|
||||||
|
generateCode(generator) {
|
||||||
|
var params = this.params || [];
|
||||||
|
var args = this.args || [];
|
||||||
|
var body = this.body;
|
||||||
|
var isStatement = this.statement;
|
||||||
|
|
||||||
|
generator.write('(');
|
||||||
|
var functionDeclaration = generator.builder.functionDeclaration(null, params, body);
|
||||||
|
var functionCall = generator.builder.functionCall(functionDeclaration, args);
|
||||||
|
generator.generateCode(functionCall);
|
||||||
|
|
||||||
|
generator.write(')');
|
||||||
|
|
||||||
|
if (isStatement) {
|
||||||
|
generator.write('\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = SelfInvokingFunction;
|
||||||
@ -12,6 +12,7 @@ class Vars extends Node {
|
|||||||
generateCode(generator) {
|
generateCode(generator) {
|
||||||
var declarations = this.declarations;
|
var declarations = this.declarations;
|
||||||
var kind = this.kind;
|
var kind = this.kind;
|
||||||
|
var isStatement = this.statement;
|
||||||
|
|
||||||
if (!declarations || !declarations.length) {
|
if (!declarations || !declarations.length) {
|
||||||
return;
|
return;
|
||||||
@ -43,7 +44,7 @@ class Vars extends Node {
|
|||||||
initValue = declaration.value;
|
initValue = declaration.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (initValue) {
|
if (initValue != null) {
|
||||||
generator.write(' = ');
|
generator.write(' = ');
|
||||||
generator.generateCode(initValue);
|
generator.generateCode(initValue);
|
||||||
}
|
}
|
||||||
@ -51,7 +52,9 @@ class Vars extends Node {
|
|||||||
if (i < declarations.length - 1) {
|
if (i < declarations.length - 1) {
|
||||||
generator.write(',\n');
|
generator.write(',\n');
|
||||||
} else {
|
} else {
|
||||||
generator.write(';\n');
|
if (isStatement) {
|
||||||
|
generator.write(';\n');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -55,27 +55,28 @@ exports.scanDir = function(autoTestDir, run, options) {
|
|||||||
files = fs.readdirSync(autoTestDir);
|
files = fs.readdirSync(autoTestDir);
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
console.warn('autotest directory does not exist: ' + autoTestDir);
|
console.warn('autotest directory does not exist: ' + autoTestDir);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
files.forEach(function(name) {
|
if (files) {
|
||||||
if (name.charAt(0) === '.') {
|
files.forEach(function(name) {
|
||||||
return;
|
if (name.charAt(0) === '.') {
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var itFunc = it;
|
var itFunc = it;
|
||||||
|
|
||||||
if (enabledTest && name === enabledTest) {
|
if (enabledTest && name === enabledTest) {
|
||||||
itFunc = it.only;
|
itFunc = it.only;
|
||||||
}
|
}
|
||||||
|
|
||||||
var dir = path.join(autoTestDir, name);
|
var dir = path.join(autoTestDir, name);
|
||||||
|
|
||||||
|
itFunc(`[${name}] `, function() {
|
||||||
|
autoTest(name, dir, run, options);
|
||||||
|
});
|
||||||
|
|
||||||
itFunc(`[${name}] `, function() {
|
|
||||||
autoTest(name, dir, run, options);
|
|
||||||
});
|
});
|
||||||
|
}
|
||||||
});
|
|
||||||
|
|
||||||
var pendingFiles;
|
var pendingFiles;
|
||||||
try {
|
try {
|
||||||
|
|||||||
27
test/fixtures/render/autotest/for-range/template.marko
vendored
Normal file
27
test/fixtures/render/autotest/for-range/template.marko
vendored
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<for(i from 0 to 9)>
|
||||||
|
${i}
|
||||||
|
</for>
|
||||||
|
-
|
||||||
|
<for(i from 9 to 0)>
|
||||||
|
${i}
|
||||||
|
</for>
|
||||||
|
-
|
||||||
|
<for(i from 9 to 0 step -1)>
|
||||||
|
${i}
|
||||||
|
</for>
|
||||||
|
-
|
||||||
|
<for(i from 0 to 9 step 2)>
|
||||||
|
${i}
|
||||||
|
</for>
|
||||||
|
-
|
||||||
|
<for(i from 9 to 0 step -2)>
|
||||||
|
${i}
|
||||||
|
</for>
|
||||||
|
-
|
||||||
|
<for(i from 0 to 'abc'.length)>
|
||||||
|
${i}
|
||||||
|
</for>
|
||||||
|
-
|
||||||
|
<for(i from ''.length to 'abc'.length)>
|
||||||
|
${i}
|
||||||
|
</for>
|
||||||
Loading…
x
Reference in New Issue
Block a user