mirror of
https://github.com/marko-js/marko.git
synced 2025-12-08 19:26:05 +00:00
Merge branch 'perf' of github.com:patrick-steele-idem/marko
Conflicts: package.json
This commit is contained in:
commit
209a4de099
10
CHANGELOG.md
10
CHANGELOG.md
@ -5,6 +5,16 @@ Changelog
|
||||
|
||||
## 2.5.x
|
||||
|
||||
### 2.6.0
|
||||
|
||||
- Performance improvements
|
||||
- `'use strict';`
|
||||
- Optimized render code paths
|
||||
- Code cleanup
|
||||
- Compatibility fixes for Node.js 0.12
|
||||
- Bad: `fs.readFile(path, 'utf8')`
|
||||
- Good: `fs.readFile(path, {encoding: 'utf8'})`
|
||||
|
||||
### 2.5.0
|
||||
|
||||
- Fixes #78 - Custom Node.js require extension for Marko template files. Example usage:
|
||||
|
||||
@ -369,7 +369,7 @@ template.render({
|
||||
|
||||
```javascript
|
||||
var template = require('marko').load('template.marko');
|
||||
var out = require('fs').createWriteStream('index.html', 'utf8');
|
||||
var out = require('fs').createWriteStream('index.html', {encoding: 'utf8'});
|
||||
|
||||
// Render the template to 'index.html'
|
||||
template.stream({
|
||||
@ -383,7 +383,7 @@ Alternatively, you can render directly to an existing stream to avoid creating a
|
||||
|
||||
```javascript
|
||||
var template = require('marko').load('template.marko');
|
||||
var out = require('fs').createWriteStream('index.html', 'utf8');
|
||||
var out = require('fs').createWriteStream('index.html', {encoding: 'utf8'});
|
||||
|
||||
// Render the template to 'index.html'
|
||||
template.render({
|
||||
@ -414,7 +414,7 @@ var fs = require('fs');
|
||||
var marko = require('marko');
|
||||
var template = marko.load('template.marko');
|
||||
|
||||
var out = marko.createWriter(fs.createWriteStream('index.html', 'utf8'));
|
||||
var out = marko.createWriter(fs.createWriteStream('index.html', {encoding: 'utf8'}));
|
||||
|
||||
// Render the first chunk asynchronously (after 1s delay):
|
||||
var asyncOut = out.beginAsync();
|
||||
|
||||
@ -491,6 +491,11 @@ TemplateBuilder.prototype = {
|
||||
} else {
|
||||
params = ['out'];
|
||||
}
|
||||
|
||||
// Don't use "use strict" in compiled templates since it
|
||||
// could break backwards compatibility.
|
||||
// out.append('"use strict";\n');
|
||||
|
||||
out.append('function create(__helpers) {\n');
|
||||
//Write out the static variables
|
||||
this.writer.flush();
|
||||
|
||||
@ -3,6 +3,7 @@ var fs = require('fs');
|
||||
var jsonminify = require('jsonminify');
|
||||
var tagDefFromCode = require('./tag-def-from-code');
|
||||
var loader = require('./loader');
|
||||
var fsReadOptions = { encoding: 'utf8' };
|
||||
|
||||
function createDefaultTagDef() {
|
||||
return {
|
||||
@ -62,7 +63,7 @@ module.exports = function scanTagsDir(tagsConfigPath, tagsConfigDirname, dir, ta
|
||||
|
||||
if (fs.existsSync(tagFile)) {
|
||||
// marko-tag.json exists in the directory, use that as the tag definition
|
||||
tagDef = JSON.parse(jsonminify(fs.readFileSync(tagFile, {encoding: 'utf8'})));
|
||||
tagDef = JSON.parse(jsonminify(fs.readFileSync(tagFile, fsReadOptions)));
|
||||
if (!tagDef.renderer && !tagDef.template) {
|
||||
if (fs.existsSync(rendererFile)) {
|
||||
tagDef.renderer = rendererFile;
|
||||
@ -95,7 +96,7 @@ module.exports = function scanTagsDir(tagsConfigPath, tagsConfigDirname, dir, ta
|
||||
exTemplateFile = templateFile + ".html";
|
||||
}
|
||||
if(exTemplateFile){
|
||||
var templateCode = fs.readFileSync(exTemplateFile, {encoding: 'utf8'});
|
||||
var templateCode = fs.readFileSync(exTemplateFile, fsReadOptions);
|
||||
tagDef = tagDefFromCode.extractTagDef(templateCode);
|
||||
if (!tagDef) {
|
||||
tagDef = createDefaultTagDef();
|
||||
@ -106,7 +107,7 @@ module.exports = function scanTagsDir(tagsConfigPath, tagsConfigDirname, dir, ta
|
||||
}
|
||||
|
||||
if (rendererJSFile) {
|
||||
var rendererCode = fs.readFileSync(rendererJSFile, {encoding: 'utf8'});
|
||||
var rendererCode = fs.readFileSync(rendererJSFile, fsReadOptions);
|
||||
tagDef = tagDefFromCode.extractTagDef(rendererCode);
|
||||
if (!tagDef) {
|
||||
tagDef = createDefaultTagDef();
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
var fs = require('fs');
|
||||
var jsonminify = require('jsonminify');
|
||||
var fsReadOptions = { encoding: 'utf8' };
|
||||
|
||||
exports.readTaglib = function (path) {
|
||||
var json = fs.readFileSync(path, 'utf8');
|
||||
var json = fs.readFileSync(path, fsReadOptions);
|
||||
|
||||
try {
|
||||
var taglibProps = JSON.parse(jsonminify(json));
|
||||
|
||||
132
package.json
132
package.json
@ -1,67 +1,67 @@
|
||||
{
|
||||
"name": "marko",
|
||||
"description": "Marko is an extensible, streaming, asynchronous, high performance, HTML-based templating language that can be used in Node.js or in the browser.",
|
||||
"keywords": [
|
||||
"templating",
|
||||
"template",
|
||||
"async",
|
||||
"streaming"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/raptorjs/marko.git"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "node_modules/.bin/mocha --ui bdd --reporter spec ./test && node_modules/.bin/jshint compiler/ runtime/ taglibs/",
|
||||
"test-fast": "node_modules/.bin/mocha --ui bdd --reporter spec ./test/render-test",
|
||||
"test-async": "node_modules/.bin/mocha --ui bdd --reporter spec ./test/render-async-test",
|
||||
"test-taglib-loader": "node_modules/.bin/mocha --ui bdd --reporter spec ./test/taglib-loader-test",
|
||||
"jshint": "node_modules/.bin/jshint compiler/ runtime/ taglibs/"
|
||||
},
|
||||
"author": "Patrick Steele-Idem <pnidem@gmail.com>",
|
||||
"maintainers": [
|
||||
"Patrick Steele-Idem <pnidem@gmail.com>"
|
||||
],
|
||||
"dependencies": {
|
||||
"app-module-path": "^1.0.0",
|
||||
"async-writer": "^1.1.2",
|
||||
"browser-refresh-client": "^1.0.0",
|
||||
"char-props": "~0.1.5",
|
||||
"events": "^1.0.2",
|
||||
"htmlparser2": "^3.7.2",
|
||||
"jsonminify": "^0.2.3",
|
||||
"marko-async": "^2.0.0",
|
||||
"marko-layout": "^2.0.0",
|
||||
"minimatch": "^0.2.14",
|
||||
"property-handlers": "^1.0.0",
|
||||
"raptor-args": "^1.0.0",
|
||||
"raptor-json": "^1.0.1",
|
||||
"raptor-logging": "^1.0.1",
|
||||
"raptor-modules": "^1.0.5",
|
||||
"raptor-polyfill": "^1.0.0",
|
||||
"raptor-promises": "^1.0.1",
|
||||
"raptor-regexp": "^1.0.0",
|
||||
"raptor-strings": "^1.0.0",
|
||||
"raptor-util": "^1.0.0",
|
||||
"resolve-from": "^1.0.0",
|
||||
"sax": "^0.6.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"chai": "~1.8.1",
|
||||
"dustjs-linkedin": "^2.3.4",
|
||||
"jshint": "^2.5.0",
|
||||
"mocha": "~1.15.1",
|
||||
"raptor-cache": "^1.1.1",
|
||||
"raptor-data-providers": "^1.0.1-beta",
|
||||
"through": "^2.3.4"
|
||||
},
|
||||
"license": "Apache License v2.0",
|
||||
"bin": {
|
||||
"markoc": "bin/markoc"
|
||||
},
|
||||
"main": "runtime/marko-runtime.js",
|
||||
"publishConfig": {
|
||||
"registry": "https://registry.npmjs.org/"
|
||||
},
|
||||
"version": "2.5.2"
|
||||
}
|
||||
"name": "marko",
|
||||
"description": "Marko is an extensible, streaming, asynchronous, high performance, HTML-based templating language that can be used in Node.js or in the browser.",
|
||||
"keywords": [
|
||||
"templating",
|
||||
"template",
|
||||
"async",
|
||||
"streaming"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/raptorjs/marko.git"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "node_modules/.bin/mocha --ui bdd --reporter spec ./test && node_modules/.bin/jshint compiler/ runtime/ taglibs/",
|
||||
"test-fast": "node_modules/.bin/mocha --ui bdd --reporter spec ./test/render-test",
|
||||
"test-async": "node_modules/.bin/mocha --ui bdd --reporter spec ./test/render-async-test",
|
||||
"test-taglib-loader": "node_modules/.bin/mocha --ui bdd --reporter spec ./test/taglib-loader-test",
|
||||
"jshint": "node_modules/.bin/jshint compiler/ runtime/ taglibs/"
|
||||
},
|
||||
"author": "Patrick Steele-Idem <pnidem@gmail.com>",
|
||||
"maintainers": [
|
||||
"Patrick Steele-Idem <pnidem@gmail.com>"
|
||||
],
|
||||
"dependencies": {
|
||||
"app-module-path": "^1.0.0",
|
||||
"async-writer": "^1.4.0",
|
||||
"browser-refresh-client": "^1.0.0",
|
||||
"char-props": "~0.1.5",
|
||||
"events": "^1.0.2",
|
||||
"htmlparser2": "^3.7.2",
|
||||
"jsonminify": "^0.2.3",
|
||||
"marko-async": "^2.0.0",
|
||||
"marko-layout": "^2.0.0",
|
||||
"minimatch": "^0.2.14",
|
||||
"property-handlers": "^1.0.0",
|
||||
"raptor-args": "^1.0.0",
|
||||
"raptor-json": "^1.0.1",
|
||||
"raptor-logging": "^1.0.1",
|
||||
"raptor-modules": "^1.0.5",
|
||||
"raptor-polyfill": "^1.0.0",
|
||||
"raptor-promises": "^1.0.1",
|
||||
"raptor-regexp": "^1.0.0",
|
||||
"raptor-strings": "^1.0.0",
|
||||
"raptor-util": "^1.0.0",
|
||||
"resolve-from": "^1.0.0",
|
||||
"sax": "^0.6.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"chai": "~1.8.1",
|
||||
"dustjs-linkedin": "^2.3.4",
|
||||
"jshint": "^2.5.0",
|
||||
"mocha": "~1.15.1",
|
||||
"raptor-cache": "^1.1.1",
|
||||
"raptor-data-providers": "^1.0.1-beta",
|
||||
"through": "^2.3.4"
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
"bin": {
|
||||
"markoc": "bin/markoc"
|
||||
},
|
||||
"main": "runtime/marko-runtime.js",
|
||||
"publishConfig": {
|
||||
"registry": "https://registry.npmjs.org/"
|
||||
},
|
||||
"version": "2.6.0"
|
||||
}
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
'use strict';
|
||||
var escapeXml = require('raptor-util/escapeXml');
|
||||
var escapeXmlAttr = escapeXml.attr;
|
||||
var runtime = require('./'); // Circular dependnecy, but that is okay
|
||||
|
||||
@ -3,6 +3,7 @@ var fs = require('fs');
|
||||
var Module = require('module').Module;
|
||||
var markoCompiler = require('../compiler');
|
||||
var cwd = process.cwd();
|
||||
var fsReadOptions = {encoding: 'utf8'};
|
||||
|
||||
if (process.env.hasOwnProperty('MARKO_HOT_RELOAD')) {
|
||||
require('../hot-reload').enable();
|
||||
@ -42,14 +43,14 @@ module.exports = function load(templatePath) {
|
||||
return require(targetFile);
|
||||
}
|
||||
|
||||
var templateSrc = fs.readFileSync(templatePath, {encoding: 'utf8'});
|
||||
var templateSrc = fs.readFileSync(templatePath, fsReadOptions);
|
||||
var compiledSrc = compiler.compile(templateSrc);
|
||||
|
||||
// console.log('Compiled code for "' + templatePath + '":\n' + compiledSrc);
|
||||
|
||||
var filename = nodePath.basename(targetFile);
|
||||
var tempFile = nodePath.join(targetDir, '.' + process.pid + '.' + Date.now() + '.' + filename);
|
||||
fs.writeFileSync(tempFile, compiledSrc, {encoding: 'utf8'});
|
||||
fs.writeFileSync(tempFile, compiledSrc, fsReadOptions);
|
||||
fs.renameSync(tempFile, targetFile);
|
||||
|
||||
return require(targetFile);
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
// async-writer provides all of the magic to support asynchronous
|
||||
// rendering to a stream
|
||||
|
||||
|
||||
'use strict';
|
||||
/**
|
||||
* Method is for internal usage only. This method
|
||||
* is invoked by code in a compiled Marko template and
|
||||
@ -36,6 +36,8 @@ exports.c = function createTemplate(path) {
|
||||
return new Template(path);
|
||||
};
|
||||
|
||||
var BUFFER_OPTIONS = { buffer: true };
|
||||
|
||||
var asyncWriter = require('async-writer');
|
||||
|
||||
// helpers can the core set of utility methods
|
||||
@ -67,10 +69,25 @@ if (streamPath) {
|
||||
stream = require(streamPath);
|
||||
}
|
||||
|
||||
function renderCallback(renderFunc, data, globalData, callback) {
|
||||
var out = new AsyncWriter();
|
||||
if (globalData) {
|
||||
extend(out.global, globalData);
|
||||
}
|
||||
|
||||
renderFunc(data, out);
|
||||
return out.end()
|
||||
.on('finish', function() {
|
||||
callback(null, out.getOutput(), out);
|
||||
})
|
||||
.once('error', callback);
|
||||
}
|
||||
|
||||
function Template(path, func, options) {
|
||||
this.path = path;
|
||||
this._ = func;
|
||||
this.buffer = !options || options.buffer !== false;
|
||||
this._options = !options || options.buffer !== false ?
|
||||
BUFFER_OPTIONS : null;
|
||||
}
|
||||
|
||||
Template.prototype = {
|
||||
@ -96,67 +113,83 @@ Template.prototype = {
|
||||
}
|
||||
|
||||
this._(data, out);
|
||||
out.end();
|
||||
return out.getOutput();
|
||||
},
|
||||
|
||||
/**
|
||||
* Renders a template to either a stream (if the last
|
||||
* argument is a Stream instance) or
|
||||
* provides the output to a callback function (if the last
|
||||
* argument is a Function).
|
||||
*
|
||||
* Supported signatures:
|
||||
*
|
||||
* render(data, callback)
|
||||
* render(data, out)
|
||||
* render(data, stream)
|
||||
* render(data, out, callback)
|
||||
* render(data, stream, callback)
|
||||
*
|
||||
* @param {Object} data The view model data for the template
|
||||
* @param {AsyncWriter} out A Stream or an AsyncWriter instance
|
||||
* @param {Function} callback A callback function
|
||||
* @return {AsyncWriter} Returns the AsyncWriter instance that the template is rendered to
|
||||
*/
|
||||
render: function(data, out) {
|
||||
render: function(data, out, callback) {
|
||||
var renderFunc = this._;
|
||||
var finalData;
|
||||
var globalData;
|
||||
if (data) {
|
||||
finalData = data;
|
||||
|
||||
if ((globalData = data.$global)) {
|
||||
// We will *move* the "$global" property
|
||||
// into the "out.global" object
|
||||
delete data.$global;
|
||||
}
|
||||
} else {
|
||||
finalData = {};
|
||||
}
|
||||
|
||||
if (typeof out === 'function') {
|
||||
// Short circuit for render(data, callback)
|
||||
return renderCallback(renderFunc, finalData, globalData, out);
|
||||
}
|
||||
|
||||
// NOTE: We create new vars here to avoid a V8 de-optimization due
|
||||
// to the following:
|
||||
// Assignment to parameter in arguments object
|
||||
var finalOut = out;
|
||||
var finalData = data || {};
|
||||
|
||||
var renderFunc = this._;
|
||||
|
||||
// callback is last argument if provided
|
||||
var callback = arguments[arguments.length - 1];
|
||||
|
||||
var shouldEnd = false;
|
||||
|
||||
if (typeof callback === 'function') {
|
||||
if (arguments.length === 2) {
|
||||
// render called with data and callback,
|
||||
// we need to create the "out"
|
||||
finalOut = null;
|
||||
}
|
||||
|
||||
if (arguments.length === 3) {
|
||||
// render(data, out, callback)
|
||||
if (!finalOut || !finalOut.isAsyncWriter) {
|
||||
finalOut = new AsyncWriter(finalOut);
|
||||
shouldEnd = true;
|
||||
}
|
||||
|
||||
finalOut.on('finish', function() {
|
||||
callback(null, finalOut.getOutput(), finalOut);
|
||||
});
|
||||
|
||||
finalOut.once('error', callback);
|
||||
finalOut
|
||||
.on('finish', function() {
|
||||
callback(null, finalOut.getOutput(), finalOut);
|
||||
})
|
||||
.once('error', callback);
|
||||
} else if (!finalOut || !finalOut.isAsyncWriter) {
|
||||
var stream = finalOut;
|
||||
// Assume the "finalOut" is really a stream
|
||||
//
|
||||
// By default, we will buffer rendering to a stream to prevent
|
||||
// the response from being "too chunky".
|
||||
var options = this.buffer ? { buffer: true } : null;
|
||||
finalOut = asyncWriter.create(stream, options);
|
||||
finalOut = asyncWriter.create(finalOut, this._options);
|
||||
shouldEnd = true;
|
||||
}
|
||||
|
||||
if (finalData.$global) {
|
||||
finalOut.global = extend(finalOut.global, finalData.$global);
|
||||
delete finalData.$global;
|
||||
if (globalData) {
|
||||
extend(out.global, globalData);
|
||||
}
|
||||
|
||||
// Invoke the compiled template's render function to have it
|
||||
// write out strings to the provided out.
|
||||
renderFunc(finalData, finalOut);
|
||||
|
||||
// Automatically end output stream (the writer) if we
|
||||
@ -167,27 +200,23 @@ Template.prototype = {
|
||||
// If out parameter was originally an AsyncWriter then
|
||||
// we assume that we are writing to output that was
|
||||
// created in the context of another rendering job.
|
||||
if (shouldEnd) {
|
||||
finalOut.end();
|
||||
}
|
||||
|
||||
return finalOut;
|
||||
return shouldEnd ? finalOut.end() : finalOut;
|
||||
},
|
||||
stream: function(data) {
|
||||
if (!stream) {
|
||||
throw new Error('Module not found: stream');
|
||||
}
|
||||
|
||||
return new Readable(this, data, this.buffer);
|
||||
return new Readable(this, data, this._options);
|
||||
}
|
||||
};
|
||||
|
||||
if (stream) {
|
||||
Readable = function(template, data, buffer) {
|
||||
Readable = function(template, data, options) {
|
||||
Readable.$super.call(this);
|
||||
this._t = template;
|
||||
this._d = data;
|
||||
this._buffer = buffer;
|
||||
this._options = options;
|
||||
this._rendered = false;
|
||||
};
|
||||
|
||||
@ -210,7 +239,7 @@ if (stream) {
|
||||
var template = this._t;
|
||||
var data = this._d;
|
||||
|
||||
var out = asyncWriter.create(this, this._buffer ? { buffer: true } : null);
|
||||
var out = asyncWriter.create(this, this._options);
|
||||
template.render(data, out);
|
||||
out.end();
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user