Renamed "context" to "out"

This commit is contained in:
Patrick Steele-Idem 2014-09-19 09:33:04 -06:00
parent 6b603568aa
commit 33ab7744a9
19 changed files with 164 additions and 207 deletions

View File

@ -17,7 +17,7 @@ Marko is an extensible, streaming, asynchronous, [high performance](https://gith
- [Callback API](#callback-api)
- [Streaming API](#streaming-api)
- [Synchronous API](#synchronous-api)
- [Asynchronous Render Context API](#asynchronous-render-context-api)
- [Asynchronous Rendering API](#asynchronous-rendering-api)
- [Browser-side Rendering](#browser-side-rendering)
- [Using the RaptorJS Optimizer](#using-the-raptorjs-optimizer)
- [Using Browserify](#using-browserify)
@ -69,7 +69,7 @@ Marko is an extensible, streaming, asynchronous, [high performance](https://gith
Most front-end developers are familiar with, and comfortable with, templating languages such as [Handlebars](https://github.com/wycats/handlebars.js), [Dust](https://github.com/linkedin/dustjs) or [Mustache](http://mustache.github.io/) so why was Marko introduced?
What makes Marko different is that it is an HTML-based templating language that does not rely on a custom language grammar. Any HTML file is a valid Marko template and vice-versa, and the Marko compiler uses an [off-the-shelf HTML parser](https://github.com/fb55/htmlparser2). Because Marko understands the HTML structure of the templates, it can do more powerful things that would not be possible in a text-based templating languages such as Handlerbars, Dust or Mustache. Marko allows developers to _extend the HTML language_ by introducing custom HTML elements and attributes. On top of that, utilizing the HTML structure for applying templating directives makes templates more readable and allows input templates to more closely resemble the final HTML structure.
What makes Marko different is that it is an HTML-based templating language that does not rely on a custom language grammar. Any HTML file is a valid Marko template and vice-versa, and the Marko compiler uses an [off-the-shelf HTML parser](https://github.com/fb55/htmlparser2). Because Marko understands the HTML structure of the templates, it can do more powerful things that would not be possible in a text-based templating languages such as Handlerbars, Dust or Mustache. Marko allows developers to _extend the HTML language_ by introducing custom HTML elements and attributes. On top of that, utilizing the HTML structure for applying templating directives makes templates more readable and allows data templates to more closely resemble the final HTML structure.
Let's compare Marko with Handlebars (a text-based templating language):
@ -176,7 +176,7 @@ Hello World!
</ul>
```
For comparison, given the following input data consisting of an empty array of colors:
For comparison, given the following data data consisting of an empty array of colors:
```javascript
{
@ -331,7 +331,7 @@ var output = template.renderSync({
console.log('Output HTML: ' + output);
```
### Asynchronous Render Context API
### Asynchronous Rendering API
```javascript
var marko = require('marko');
@ -339,26 +339,26 @@ var template = marko.load('template.marko');
var out = require('fs').createWriteStream('index.html', 'utf8');
var context = marko.createContext(out);
var out = marko.createWriter(out);
// Render the first chunk asynchronously (after 1s delay):
var asyncContext = context.beginAsync();
var asyncOut = out.beginAsync();
setTimeout(function() {
asyncContext.write('BEGIN ');
asyncContext.end();
asyncOut.write('BEGIN ');
asyncOut.end();
}, 1000);
// Render the template to the existing render context:
// Render the template to the original writer:
template.render({
name: 'World'
},
context);
out);
// Write the last chunk synchronously:
context.write(' END');
out.write(' END');
// End the rendering context
context.end();
// End the rendering out
out.end();
```
Despite rendering the first chunk asynchronously, the above program will stream out the output in the correct order to `index.html`:
@ -367,7 +367,7 @@ Despite rendering the first chunk asynchronously, the above program will stream
BEGIN Hello World! END
```
For more details, please see the documentation for the [raptor-render-context](https://github.com/raptorjs3/raptor-render-context) module.
For more details, please see the documentation for the [async-writer](https://github.com/raptorjs3/async-writer) module.
## Browser-side Rendering
@ -425,7 +425,7 @@ browserify -t markoify run.js > browser.js
## Template Compilation
The Marko compiler produces a Node.js-compatible, CommonJS module as output. This output format has the advantage that compiled template modules can benefit from a context-aware module loader and templates can easily be transported to work in the browser using the [RaptorJS Optimizer](https://github.com/raptorjs3/optimizer) or [Browserify](https://github.com/substack/node-browserify).
The Marko compiler produces a Node.js-compatible, CommonJS module as output. This output format has the advantage that compiled template modules can benefit from a out-aware module loader and templates can easily be transported to work in the browser using the [RaptorJS Optimizer](https://github.com/raptorjs3/optimizer) or [Browserify](https://github.com/substack/node-browserify).
The `marko` module will automatically compile templates loaded by your application on the server, but you can also choose to precompile all templates. This can be helpful as a build or test step to catch errors early.
@ -474,26 +474,26 @@ module.exports = function create(__helpers) {
forEach = __helpers.f,
escapeXmlAttr = __helpers.xa;
return function render(data, context) {
context.w('Hello ' +
return function render(data, out) {
out.w('Hello ' +
escapeXml(data.name) +
'! ');
if (notEmpty(data.colors)) {
context.w('<ul>');
out.w('<ul>');
forEach(data.colors, function(color) {
context.w('<li style="color: ' +
out.w('<li style="color: ' +
escapeXmlAttr(color) +
'">' +
escapeXml(color) +
'</li>');
});
context.w('</ul>');
out.w('</ul>');
}
else {
context.w('<div>No colors!</div>');
out.w('<div>No colors!</div>');
}
};
}
@ -624,6 +624,15 @@ Input data passed to a template is made available using a special `data` variabl
<var name="name" value="data.name.toUpperCase()" />
```
The `<with>` directive can be used to create scoped variables as shown in the following sample code:
```html
<with vars="nameUpper=data.name.toUpperCase(); nameLower=data.name.toLowerCase()">
Hello $nameUpper!
Hello $nameLower!
</with>
```
## Conditionals
### if...else-if...else
@ -859,7 +868,7 @@ The above macro can then be invoked as part of any expression. Alternatively, th
### invoke
The `<invoke>` directive can be used to invoke a function defined using the `<def>` directive or a function that is part of the input to a template. The `<invoke>` directive allows arguments to be passed using element attributes, but that format is only supported for functions that were previously defined using the `<def>` directive.
The `<invoke>` directive can be used to invoke a function defined using the `<def>` directive or a function that is part of the input data to a template. The `<invoke>` directive allows arguments to be passed using element attributes, but that format is only supported for functions that were previously defined using the `<def>` directive.
```html
<def function="greeting(name, count)">
@ -1067,23 +1076,23 @@ For more details, please see [https://github.com/raptorjs3/marko-taglib-layout](
## Tag Renderer
Every tag should be mapped to a "renderer". A renderer is just a function that takes two arguments (`input` and `context`). The `input` argument is an arbitrary object that contains the input data for the renderer. The `context` argument is an [asynchronous rendering context](https://github.com/raptorjs3/raptor-render-context) that wraps an output stream. Output can be produced using `context.write(someString)` There is no class hierarchy or tie-ins to Marko when implementing a tag renderer. A simple tag renderer is shown below:
Every tag should be mapped to a "renderer". A renderer is just a function that takes two arguments (`data` and `out`). The `data` argument is an arbitrary object that contains the data data for the renderer. The `out` argument is an [asynchronous rendering out](https://github.com/raptorjs3/async-writer) that wraps an output stream. Output can be produced using `out.write(someString)` There is no class hierarchy or tie-ins to Marko when implementing a tag renderer. A simple tag renderer is shown below:
```javascript
module.exports = function(input, context) {
context.write('Hello ' + input.name + '!');
module.exports = function(data, out) {
out.write('Hello ' + data.name + '!');
}
```
If, and only if, a tag has nested content, then a special `invokeBody` method will be added to the `input` object. If a renderer wants to render the nested body content then it must call the `invokeBody` method. For example:
If, and only if, a tag has nested content, then a special `invokeBody` method will be added to the `data` object. If a renderer wants to render the nested body content then it must call the `invokeBody` method. For example:
```javascript
module.exports = function(input, context) {
context.write('BEFORE BODY');
if (input.invokeBody) {
input.invokeBody();
module.exports = function(data, out) {
out.write('BEFORE BODY');
if (data.invokeBody) {
data.invokeBody();
}
context.write('AFTER BODY');
out.write('AFTER BODY');
}
```
@ -1248,11 +1257,11 @@ _components/tabs/renderer.js:_
var templatePath = require.resolve('./template.marko');
var template = require('marko').load(templatePath);
module.exports = function render(input, context) {
module.exports = function render(data, out) {
var nestedTabs = [];
// Invoke the body function to discover nested <ui-tab> tags
input.invokeBody({ // Invoke the body with the scoped "tabs" variable
data.invokeBody({ // Invoke the body with the scoped "tabs" variable
addTab: function(tab) {
tab.id = tab.id || ("tab" + tabs.length);
nestedTabs.push(tab);
@ -1262,16 +1271,16 @@ module.exports = function render(input, context) {
// Now render the markup for the tabs:
template.render({
tabs: nestedTabs
}, context);
}, out);
};
```
_components/tab/renderer.js:_
```javascript
module.exports = function render(input, context) {
module.exports = function render(data, out) {
// Register with parent but don't render anything
input.tabs.addTab(input);
data.tabs.addTab(data);
};
```

View File

@ -135,9 +135,9 @@ Node.prototype = {
var methodCall;
if (escapeXml !== false) {
methodCall = 'context.captureString(';
methodCall = 'out.captureString(';
} else {
methodCall = '__helpers.c(context, ';
methodCall = '__helpers.c(out, ';
}
return template.makeExpression({
@ -531,4 +531,4 @@ Node.prototype = {
return this.escapeXmlContext;
}
};
module.exports = Node;
module.exports = Node;

View File

@ -74,7 +74,7 @@ CodeWriter.prototype = {
if (!this._bufferedWrites) {
this._bufferedWrites = [];
}
this._bufferedWrites.push(expression);
@ -158,7 +158,7 @@ CodeWriter.prototype = {
function concat() {
code.append(_this.indentStr() + 'context.w(');
code.append(_this.indentStr() + 'out.w(');
_bufferedWrites.forEach(function (expression, i) {
if (i !== 0) {
@ -178,9 +178,9 @@ CodeWriter.prototype = {
function chain() {
_bufferedWrites.forEach(function (arg, i) {
if (i === 0) {
this._code.append(this.indentStr() + 'context.w(');
this._code.append(this.indentStr() + 'out.w(');
} else {
this.incIndent();
this._code.append(this.indentStr() + '.w(');
@ -211,7 +211,7 @@ CodeWriter.prototype = {
} else {
chain();
}
}
},
incIndent: function (delta) {
@ -270,7 +270,7 @@ TemplateBuilder.prototype = {
}
},
getStaticHelperFunction: function (varName, propName) {
var added = this.helperFunctionsAdded[propName];
if (added) {
return added;
@ -285,7 +285,7 @@ TemplateBuilder.prototype = {
},
addStaticVar: function (name, expression) {
name = safeVarName(name);
if (!this.staticVarsLookup.hasOwnProperty(name)) {
this.staticVarsLookup[name] = true;
this.staticVars.push({
@ -300,7 +300,7 @@ TemplateBuilder.prototype = {
},
addVar: function (name, expression) {
name = safeVarName(name);
this.vars[name] = true;
this.vars.push({
name: name,
@ -354,7 +354,7 @@ TemplateBuilder.prototype = {
if (!this.hasExpression(templatePath)) {
// Resolve the static string to a full path only once
templateVar = this.addStaticVar(templatePath, '__helpers.l(require.resolve(' + this.compiler.convertType(templatePath, 'string', true) + '))');
this.statement(this.makeExpression(templateVar + '.render(' + dataExpression + ', context);'));
this.statement(this.makeExpression(templateVar + '.render(' + dataExpression + ', out);'));
return;
}
}
@ -379,7 +379,7 @@ TemplateBuilder.prototype = {
contextHelperMethodCall: function (methodName, args) {
if (!this.hasErrors()) {
args = arrayFromArguments(arguments, 1);
args.unshift('context');
args.unshift('out');
this.writer.functionCall('__helpers.' + methodName, args);
}
return this;
@ -444,18 +444,18 @@ TemplateBuilder.prototype = {
return '';
}
var out = new StringBuilder();
var params = this.params;
if (params) {
params = ['context'].concat(params);
params = ['out'].concat(params);
} else {
params = ['context'];
params = ['out'];
}
out.append('module.exports = function create(__helpers) {\n');
//Write out the static variables
this.writer.flush();
this._writeVars(this.staticVars, out, INDENT);
out.append('\n' + INDENT + 'return function render(data, context) {\n');
out.append('\n' + INDENT + 'return function render(data, out) {\n');
//Write out the render variables
if (this.vars && this.vars.length) {
this._writeVars(this.vars, out, INDENT + INDENT);
@ -510,4 +510,4 @@ TemplateBuilder.prototype = {
},
INDENT: INDENT
};
module.exports = TemplateBuilder;
module.exports = TemplateBuilder;

View File

@ -31,7 +31,7 @@
"raptor-polyfill": "^1.0.0-beta",
"raptor-promises": "^1.0.0-beta",
"raptor-regexp": "^1.0.0-beta",
"raptor-render-context": "^1.0.0-beta",
"async-writer": "^1.0.0-beta",
"raptor-strings": "^1.0.0-beta",
"marko-taglib-async": "^1.1.0",
"marko-taglib-layout": "^1.1.0",
@ -56,4 +56,4 @@
"registry": "https://registry.npmjs.org/"
},
"version": "1.2.2"
}
}

View File

@ -20,14 +20,14 @@
* <p>The code for the Marko compiler is kept separately
* in the {@link raptor/templating/compiler} module.
*/
var renderContext = require('raptor-render-context');
var Context = renderContext.Context;
var asyncWriter = require('async-writer');
var helpers = require('./helpers');
var loader = require('./loader');
var cache = {};
var Readable;
var AsyncWriter = asyncWriter.AsyncWriter;
exports.Context = Context;
exports.AsyncWriter = AsyncWriter;
var stream;
@ -43,16 +43,16 @@ if (streamPath) {
}
function renderWithCallback(template, data, context, callback) {
context
function renderWithCallback(template, data, out, callback) {
out
.on('end', function() {
callback(null, context.getOutput());
callback(null, out.getOutput());
})
.on('error', callback);
template._(data, context); //Invoke the template rendering function with the required arguments
template._(data, out); //Invoke the template rendering function with the required arguments
context.end();
out.end();
}
function Template(renderFunc) {
@ -61,13 +61,13 @@ function Template(renderFunc) {
Template.prototype = {
renderSync: function(data) {
var context = new Context();
context.sync();
this._(data, context);
context.end();
return context.getOutput();
var out = new AsyncWriter();
out.sync();
this._(data, out);
out.end();
return out.getOutput();
},
render: function(data, context, callback) {
render: function(data, out, callback) {
if (data == null) {
data = {};
}
@ -75,23 +75,23 @@ Template.prototype = {
// callback is last argument if provided
callback = arguments[arguments.length - 1];
if (typeof callback === 'function') {
if (arguments.length === 2) { // data, context, callback
callback = context;
context = new Context();
if (arguments.length === 2) { // data, out, callback
callback = out;
out = new AsyncWriter();
}
renderWithCallback(this, data, context, callback);
renderWithCallback(this, data, out, callback);
} else {
if (context.isRenderContext) {
this._(data, context);
if (out.isRenderContext) {
this._(data, out);
} else {
// Assume the "context" is really a stream
context = new Context(context);
this._(data, context);
context.end(); // End the context and the underlying stream
// Assume the "out" is really a stream
out = new AsyncWriter(out);
this._(data, out);
out.end(); // End the out and the underlying stream
}
}
return context;
return out;
},
stream: function(data) {
if (!stream) {
@ -131,9 +131,9 @@ if (stream) {
var template = this._t;
var data = this._d;
var context = exports.createContext(this);
template.render(data, context);
context.end();
var out = exports.createWriter(this);
template.render(data, out);
out.end();
}
};
@ -158,8 +158,8 @@ function load(templatePath) {
exports.load = load;
exports.render = function (templatePath, data, context) {
return load(templatePath).render(data, context);
exports.render = function (templatePath, data, out) {
return load(templatePath).render(data, out);
};
exports.stream = function(templatePath, data) {
@ -170,8 +170,8 @@ exports.unload = function(templatePath) {
delete cache[templatePath];
};
exports.createContext = function(writer) {
return new Context(writer);
exports.createWriter = function(writer) {
return new AsyncWriter(writer);
};
exports.helpers = helpers;

View File

@ -5,7 +5,7 @@ var req = require; // Fool the optimizer
module.exports = {
render: function (input, context) {
render: function (input, out) {
if (raptorCache === undefined) {
try {
raptorCache = req('raptor-cache');
@ -25,7 +25,7 @@ module.exports = {
}
});
}
var cacheKey = input.cacheKey;
if (!cacheKey) {
throw new Error('cache-key is required for <cached-fragment>');
@ -34,13 +34,13 @@ module.exports = {
var cacheManager = input.cacheManager || defaultCacheManager;
var cache = cacheManager.getCache(input.cacheName || 'marko/cached-fragment');
var asyncContext = context.beginAsync();
var asyncContext = out.beginAsync();
cache.get(cacheKey,
{
builder: function(callback) {
var result = context.captureString(function () {
var result = out.captureString(function () {
if (input.invokeBody) {
input.invokeBody();
}
@ -51,7 +51,7 @@ module.exports = {
if (err) {
return asyncContext.error(err);
}
asyncContext.end(result);
});
}

View File

@ -51,13 +51,13 @@ DefNode.prototype = {
if (func.indexOf('(') === -1) {
func += '()';
}
template.statement('function ' + func + ' {').indent(function () {
template.line('return __helpers.c(context, function() {').indent(function () {
template.line('return __helpers.c(out, function() {').indent(function () {
this.generateCodeForChildren(template);
}, this).line('});');
}, this).line('}');
}
};
module.exports = DefNode;
module.exports = DefNode;

View File

@ -50,7 +50,7 @@ function getPropsStr(props, template) {
});
});
if (propsArray.length) {
return '{\n' + propsArray.join(',\n') + '\n' + template.indentStr() + '}';
} else {
@ -107,7 +107,7 @@ TagHandlerNode.prototype = {
this.tag.forEachImportedVariable(function (importedVariable) {
this.setProperty(importedVariable.targetProperty, template.makeExpression(importedVariable.expression));
}, this);
var _this = this;
var variableNames = [];
_this.tag.forEachVariable(function (nestedVar) {
@ -149,7 +149,7 @@ TagHandlerNode.prototype = {
}
template.functionCall(tagHelperVar, function () {
template.code('context,\n').indent(function () {
template.code('out,\n').indent(function () {
template.line(handlerVar + ',').indent();
if (_this.inputExpression) {
template.code(_this.inputExpression);
@ -176,4 +176,4 @@ TagHandlerNode.prototype = {
}
};
module.exports = TagHandlerNode;
module.exports = TagHandlerNode;

View File

@ -1,8 +1,8 @@
'use strict';
module.exports = function render(input, context) {
context.write('<!--');
module.exports = function render(input, out) {
out.write('<!--');
if (input.invokeBody) {
input.invokeBody();
}
context.write('-->');
};
out.write('-->');
};

View File

@ -35,7 +35,7 @@ describe('marko/api' , function() {
});
it('should allow a template to be rendered to a context wrapping a string builder', function(done) {
var context = marko.createContext();
var context = marko.createWriter();
context
.on('end', function() {
expect(context.getOutput()).to.equal('Hello John!');
@ -62,7 +62,7 @@ describe('marko/api' , function() {
output += data;
});
var context = marko.createContext(stream);
var context = marko.createWriter(stream);
context
.on('end', function() {
expect(output).to.equal('Hello John!');
@ -125,7 +125,7 @@ describe('marko/api' , function() {
});
it('should allow a template to be loaded and rendered to a context wrapping a string builder', function(done) {
var context = marko.createContext();
var context = marko.createWriter();
context
.on('end', function() {
expect(context.getOutput()).to.equal('Hello John!');
@ -152,7 +152,7 @@ describe('marko/api' , function() {
output += data;
});
var context = marko.createContext(stream);
var context = marko.createWriter(stream);
context
.on('end', function() {
expect(output).to.equal('Hello John!');

View File

@ -52,7 +52,7 @@ function testRender(path, data, done, options) {
} catch(e) {
return done(e);
}
});
});
}
describe('marko/dust' , function() {
@ -98,4 +98,3 @@ describe('marko/dust' , function() {
});
});

View File

@ -26,7 +26,7 @@ function testRender(path, data, done, options) {
var compiler = require('../compiler').createCompiler(inputPath);
var src = fs.readFileSync(inputPath, {encoding: 'utf8'});
var compiledSrc = compiler.compile(src);
fs.writeFileSync(compiledPath, compiledSrc, {encoding: 'utf8'});
@ -34,22 +34,22 @@ function testRender(path, data, done, options) {
// console.log('\nCompiled (' + inputPath + '):\n---------\n' + compiledSrc);
var marko = require('../');
var Context = marko.Context;
var context = options.context || new Context(new StringBuilder());
var AsyncWriter = marko.AsyncWriter;
var out = options.out || new AsyncWriter(new StringBuilder());
require('../compiler').defaultOptions.checkUpToDate = false;
if (options.dataProviders) {
var dataProviders = require('raptor-data-providers').forContext(context);
var dataProviders = require('raptor-data-providers').forContext(out);
dataProviders.register(options.dataProviders);
}
marko.render(inputPath, data, context)
marko.render(inputPath, data, out)
.on('end', function() {
var output = context.getOutput();
var output = out.getOutput();
fs.writeFileSync(actualPath, output, {encoding: 'utf8'});
@ -72,7 +72,7 @@ function testRender(path, data, done, options) {
.on('error', done)
.end();
}
describe('marko/marko-async' , function() {
@ -99,7 +99,7 @@ describe('marko/marko-async' , function() {
'D3': delayedDataProvider(200),
'D4': delayedDataProvider(800)
}
});
});
});
it('should render a simple template with async fragments correctly (2)', function(done) {
@ -110,7 +110,7 @@ describe('marko/marko-async' , function() {
'D3': delayedDataProvider(300),
'D4': delayedDataProvider(150)
}
});
});
});
it('should render a simple template with async fragments correctly (3)', function(done) {
@ -121,7 +121,7 @@ describe('marko/marko-async' , function() {
'D3': delayedDataProvider(300),
'D4': delayedDataProvider(100)
}
});
});
});
it('should render a simple template with async fragments correctly (4)', function(done) {
@ -132,7 +132,7 @@ describe('marko/marko-async' , function() {
'D3': delayedDataProvider(200),
'D4': delayedDataProvider(100)
}
});
});
});
it('should render a less simple template with async fragments correctly (1)', function(done) {
@ -146,7 +146,7 @@ describe('marko/marko-async' , function() {
'D6': delayedDataProvider(100),
'D7': delayedDataProvider(50)
}
});
});
});
it('should render a less simple template with async fragments correctly (2)', function(done) {
@ -160,7 +160,7 @@ describe('marko/marko-async' , function() {
'D6': delayedDataProvider(100),
'D7': delayedDataProvider(200)
}
});
});
});
it('should render a less simple template with async fragments correctly (3)', function(done) {
@ -174,7 +174,7 @@ describe('marko/marko-async' , function() {
'D6': delayedDataProvider(100),
'D7': delayedDataProvider(200)
}
});
});
});
it("should allow for using macros inside async fragments", function(done) {
@ -182,10 +182,10 @@ describe('marko/marko-async' , function() {
dataProviders: {
'D1': delayedDataProvider(100)
}
});
});
});
it("should allow for shared and context-specific data providers", function(done) {
it("should allow for global data providers", function(done) {
require('raptor-data-providers').register({
'sharedData': function(args, done) {
var deferred = require('raptor-promises').defer();
@ -303,4 +303,3 @@ describe('marko/marko-async' , function() {
});
});

View File

@ -30,12 +30,12 @@ function testRender(path, data, done, options) {
require('../compiler').defaultOptions.checkUpToDate = false;
var Context = marko.Context;
var context = options.context || new Context(new StringBuilder());
var AsyncWriter = marko.AsyncWriter;
var out = options.out || new AsyncWriter(new StringBuilder());
marko.render(inputPath, data, context)
marko.render(inputPath, data, out)
.on('end', function() {
var output = context.getOutput();
var output = out.getOutput();
fs.writeFileSync(actualPath, output, {encoding: 'utf8'});
@ -273,31 +273,6 @@ describe('marko/marko' , function() {
testRender("test-project/html-templates/dynamic-attributes3.marko", {}, done);
});
// it("should allow for nodes to be converted to expressions", function(done) {
// var ElementNode = require('raptor/templating/compiler/ElementNode');
// var TextNode = require('raptor/templating/compiler/TextNode');
// var TemplateBuilder = require('raptor/templating/compiler/TemplateBuilder');
// var compiler = require('raptor/templating/compiler').createCompiler();
// var template = new TemplateBuilder(compiler);
// var div = new ElementNode("div");
// var text = new TextNode("Hello World!");
// div.appendChild(text);
// var expression = div.getExpression(template).toString();
// var bodyContentExpression = div.getBodyContentExpression(template).toString();
// var sb = require('raptor/strings').createStringBuilder();
// var context = require('raptor/templating').createContext(sb);
// var output = eval(expression);
// expect(output.toString()).toEqual('<div>Hello World!</div>');
// output = eval(bodyContentExpression);
// expect(output.toString()).toEqual('Hello World!');
// });
it("should allow for nested attributes", function(done) {
testRender("test-project/html-templates/nested-attrs.marko", {active: true}, done);
});

View File

@ -27,12 +27,12 @@ function testRender(path, data, done, options) {
require('../compiler').defaultOptions.checkUpToDate = false;
var marko = require('../');
var Context = marko.Context;
var context = options.context || new Context(new StringBuilder());
var AsyncWriter = marko.AsyncWriter;
var out = options.out || new AsyncWriter(new StringBuilder());
marko.render(inputPath, data, context)
marko.render(inputPath, data, out)
.on('end', function() {
var output = context.getOutput();
var output = out.getOutput();
fs.writeFileSync(actualPath, output, {encoding: 'utf8'});
@ -253,31 +253,6 @@ describe('marko/xml' , function() {
testRender("test-project/xml-templates/dynamic-attributes3.marko.xml", {}, done);
});
// it("should allow for nodes to be converted to expressions", function(done) {
// var ElementNode = require('raptor/templating/compiler/ElementNode');
// var TextNode = require('raptor/templating/compiler/TextNode');
// var TemplateBuilder = require('raptor/templating/compiler/TemplateBuilder');
// var compiler = require('raptor/templating/compiler').createCompiler();
// var template = new TemplateBuilder(compiler);
// var div = new ElementNode("div");
// var text = new TextNode("Hello World!");
// div.appendChild(text);
// var expression = div.getExpression(template).toString();
// var bodyContentExpression = div.getBodyContentExpression(template).toString();
// var sb = require('raptor/strings').createStringBuilder();
// var context = require('raptor/templating').createContext(sb);
// var output = eval(expression);
// expect(output.toString()).toEqual('<div>Hello World!</div>');
// output = eval(bodyContentExpression);
// expect(output.toString()).toEqual('Hello World!');
// });
it("should allow for nested attributes", function(done) {
testRender("test-project/xml-templates/nested-attrs.marko.xml", {active: true}, done);
});

View File

@ -5,8 +5,8 @@ module.exports = function create(__helpers) {
hello_renderer = require("./hello-renderer"),
_tag = __helpers.t;
return function render(data, context) {
_tag(context,
return function render(data, out) {
_tag(out,
hello_renderer,
{
"name": "World"

View File

@ -4,8 +4,8 @@ module.exports = function create(__helpers) {
notEmpty = __helpers.ne,
escapeXml = __helpers.x;
return function render(data, context) {
context.w('Hello ' +
return function render(data, out) {
out.w('Hello ' +
escapeXml(data.name) +
'! Hello ' +
str(data.name) +

View File

@ -1,6 +1,6 @@
{%
function test(name) {
context.write("Hello " + name + "!");
out.write("Hello " + name + "!");
}
%}
{%
@ -8,20 +8,20 @@
return "Hello " + name + "!";
}
%}
A
<p>
<invoke function="test('World')"/>
<c-write value="test2('World')"/>
</p>
B
<p>
<def function="greeting(name, count)">
Hello ${name}! You have ${count} new messages.
</def>
<invoke function="greeting" name="Frank" count="${10}"/>
<invoke function="greeting('John', 20)"/>
</p>
</p>

View File

@ -3,7 +3,7 @@ module.exports = function create(__helpers) {
empty = __helpers.e,
notEmpty = __helpers.ne;
return function render(data, context) {
context.w('Hello John');
return function render(data, out) {
out.w('Hello John');
};
}

View File

@ -1,7 +1,7 @@
<c-template>
{%
function test(name) {
context.write("Hello " + name + "!");
out.write("Hello " + name + "!");
}
%}
{%
@ -9,16 +9,16 @@
return "Hello " + name + "!";
}
%}
A
<p>
<invoke function="test('World')"/>
<c-write value="test2('World')"/>
</p>
B
<p>
<def function="greeting(name, count)">
Hello ${name}! You have ${count} new messages.
@ -27,4 +27,4 @@
<invoke function="greeting('John', 20)"/>
</p>
</c-template>
</c-template>