Cleaner split of the html and vdom runtimes

This commit is contained in:
Patrick Steele-Idem 2016-10-21 15:44:52 -06:00
parent af990a04b3
commit a05f15ce5d
50 changed files with 202 additions and 361 deletions

View File

@ -57,6 +57,7 @@ const helpers = {
'classList': 'cl',
'const': 'const',
'createElement': 'e',
'createInlineTemplate': 'i',
'escapeXml': 'x',
'escapeXmlAttr': 'xa',
'escapeScript': 'xs',
@ -101,7 +102,7 @@ class CompileContext extends EventEmitter {
this._preserveWhitespace = null;
this._preserveComments = null;
this.inline = this.options.inline === true;
this._moduleRuntimeTarget = this.outputType === 'vdom' ? 'marko/vdom' : 'marko';
this._moduleRuntimeTarget = this.outputType === 'vdom' ? 'marko/vdom' : 'marko/html';
this._helpersIdentifier = null;

View File

@ -39,7 +39,7 @@ class TemplateRoot extends Node {
renderStatements = renderStatements.concat(body);
if (context.inline) {
var createInlineMarkoTemplateVar = context.importModule('marko_createInlineTemplate', 'marko/runtime/inline');
var createInlineMarkoTemplateVar = context.helper('createInlineTemplate');
return builder.functionCall(
createInlineMarkoTemplateVar,

View File

@ -23,6 +23,7 @@ var nodePath = require('path');
var modifiedId = 1;
var nextTemplateId = 0;
var runtime;
var loadMarkoTemplate = require('../').load;
/**
* Lazily require the Marko runtime because there is a circular dependency.
@ -30,12 +31,12 @@ var runtime;
* Marko runtime.
*/
function _getMarkoRuntime() {
return runtime || (runtime = require('../runtime'));
return runtime || (runtime = require('../runtime/html'));
}
function tryReload(path, runtime) {
try {
return runtime.load(path);
return loadMarkoTemplate(path);
} catch(e) {
return undefined;
}

1
html.js Normal file
View File

@ -0,0 +1 @@
module.exports = require('./runtime/html');

View File

@ -77,7 +77,7 @@
"bin": {
"markoc": "bin/markoc"
},
"main": "runtime/html/index.js",
"main": "runtime/index.js",
"publishConfig": {
"registry": "https://registry.npmjs.org/"
},
@ -85,7 +85,7 @@
"./node-require.js": "./node-require-browser.js"
},
"homepage": "http://markojs.com/",
"version": "3.10.1",
"version": "4.0.0-beta.0",
"logo": {
"url": "https://raw.githubusercontent.com/marko-js/branding/master/marko-logo-small.png"
}

View File

@ -16,6 +16,7 @@
'use strict';
var isArray = Array.isArray;
var load = require('./loader');
function classListHelper(arg, classNames) {
var len;
@ -205,31 +206,6 @@ module.exports = {
}
},
// ----------------------------------
// The helpers listed below require an out
// ----------------------------------
/**
* Internal method to handle includes/partials
* @private
*/
i: function(out, template, data) {
if (!template) {
return;
}
if (typeof template.render === 'function') {
template.render(data, out);
} else {
throw new Error('Invalid template: ' + template);
}
return this;
},
/**
* Merges object properties
* @param {[type]} object [description]
@ -254,5 +230,10 @@ module.exports = {
*/
cl: function() {
return classList(arguments);
}
},
/**
* Loads a template (__helpers.l --> marko_loadTemplate(path))
*/
l: load
};

View File

@ -17,7 +17,6 @@
'use strict';
var escapeXml = require('raptor-util/escapeXml');
var escapeXmlAttr = escapeXml.attr;
var runtime = require('../'); // Circular dependency, but that is okay
var attr = require('raptor-util/attr');
var extend = require('raptor-util/extend');
@ -133,15 +132,5 @@ module.exports = extend({
}
},
/**
* Loads a template (__helpers.l --> marko_loadTemplate(path))
*/
l: function(path) {
if (typeof path === 'string') {
return runtime.load(path);
} else {
// Assume it is already a pre-loaded template
return path;
}
}
i: require('./')._inline
}, commonHelpers);

View File

@ -1,61 +1,35 @@
/*
* Copyright 2011 eBay Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* This module provides the lightweight runtime for loading and rendering
* templates. The compilation is handled by code that is part of the
* [marko/compiler](https://github.com/raptorjs/marko/tree/master/compiler)
* module. If rendering a template on the client, only the runtime is needed
* on the client and not the compiler
*/
'use strict';
// helpers provide a core set of various utility methods
// that are available in every template
var helpers = require('./helpers');
/**
* Method is for internal usage only. This method
* is invoked by code in a compiled Marko template and
* it is used to create a new Template instance.
* @private
*/
exports.c = function createTemplate(path, createFunc) {
var template = new Template(path, lazyRender);
return template;
exports.c = function createTemplate(path, createFunc) {
var template = new Template(path, lazyRender);
return template;
function lazyRender() {
template._ = createFunc(helpers);
template._.apply(template, arguments);
}
};
function lazyRender() {
template._ = createFunc(helpers);
template._.apply(template, arguments);
}
};
var BUFFER_OPTIONS = { buffer: true };
// async-writer provides all of the magic to support asynchronous
// rendering to a stream
var asyncWriter = require('async-writer');
var AsyncStream = asyncWriter.AsyncStream;
var loader;
function createOut(globalData) {
return new AsyncStream(globalData);
}
// helpers provide a core set of various utility methods
// that are available in every template (empty, notEmpty, etc.)
var helpers;
// If the optional "stream" module is available
// then Readable will be a readable stream
var AsyncStream = asyncWriter.AsyncStream;
var extend = require('raptor-util/extend');
exports.AsyncStream = AsyncStream;
@ -79,8 +53,17 @@ function Template(path, func, options) {
}
Template.prototype = {
createOut() {
return new AsyncStream();
createOut: createOut,
/**
* Internal method to initialize a loaded template with a
* given create function that was generated by the compiler.
* Warning: User code should not depend on this method.
*
* @private
* @param {Function(__helpers)} createFunc The function used to produce the render(data, out) function.
*/
c: function(createFunc) {
this._ = createFunc(helpers);
},
renderSync: function(data) {
var localData;
@ -193,86 +176,22 @@ Template.prototype = {
}
};
function createRenderProxy(template) {
return function(data, out) {
template._(data, out);
};
}
function initTemplate(rawTemplate, templatePath) {
if (rawTemplate.render) {
return rawTemplate;
}
var createFunc = rawTemplate.create || rawTemplate;
var template = createFunc.loaded;
if (!template) {
template = createFunc.loaded = new Template(templatePath);
template.c(createFunc);
}
return template;
}
function load(templatePath, templateSrc, options) {
if (!templatePath) {
throw new Error('"templatePath" is required');
}
if (arguments.length === 1) {
// templateSrc and options not provided
} else if (arguments.length === 2) {
// see if second argument is templateSrc (a String)
// or options (an Object)
var lastArg = arguments[arguments.length - 1];
if (typeof lastArg !== 'string') {
options = arguments[1];
templateSrc = undefined;
}
} else if (arguments.length === 3) {
// assume function called according to function signature
} else {
throw new Error('Illegal arguments');
}
var template;
if (typeof templatePath === 'string') {
template = initTemplate(loader(templatePath, templateSrc, options), templatePath);
} else if (templatePath.render) {
template = templatePath;
} else {
template = initTemplate(templatePath);
}
if (options && (options.buffer != null)) {
template = new Template(
template.path,
createRenderProxy(template),
options);
}
return template;
}
function createInlineMarkoTemplate(filename, renderFunc) {
return new Template(filename, renderFunc);
}
exports.load = load;
exports.createWriter = function(writer) {
return new AsyncStream(null, writer);
};
exports.helpers = helpers;
exports._inline = createInlineMarkoTemplate;
exports.Template = Template;
exports._inline = createInlineMarkoTemplate;
helpers = require('./helpers');
exports.helpers = helpers;
require('../')._setRuntime(exports);
// The loader is used to load templates that have not already been
// loaded and cached. On the server, the loader will use
// the compiler to compile the template and then load the generated
// module file using the Node.js module loader
loader = require('../loader');

16
runtime/index.js Normal file
View File

@ -0,0 +1,16 @@
var runtime;
function setRuntime(_runtime) {
runtime = _runtime;
}
exports._setRuntime = setRuntime;
var load = require('./loader');
function createOut(globalData) {
return runtime.createOut(globalData);
}
exports.createOut = createOut;
exports.load = load;

View File

@ -1 +0,0 @@
module.exports = require('./')._inline;

View File

@ -15,6 +15,27 @@
*/
'use strict';
module.exports = function load(templatePath, templateSrc, options) {
if (arguments.length === 1) {
return doLoad(templatePath);
} else if (arguments.length === 2) {
// see if second argument is templateSrc (a String)
// or options (an Object)
var lastArg = arguments[arguments.length - 1];
if (typeof lastArg === 'string') {
return doLoad(templatePath, templateSrc);
} else {
var finalOptions = templateSrc;
return doLoad(templatePath, null, finalOptions);
}
} else if (arguments.length === 3) {
// assume function called according to function signature
return doLoad(templatePath, templateSrc, options);
} else {
throw new Error('Illegal arguments');
}
};
var nodePath = require('path');
var fs = require('fs');
var Module = require('module').Module;
@ -125,38 +146,59 @@ function loadFile(templatePath, options) {
return require(targetFile);
}
module.exports = function load(templatePath, templateSrc, options) {
function createRenderProxy(template) {
return function(data, out) {
template._(data, out);
};
}
function doLoad(templatePath, templateSrc, options) {
options = Object.assign({}, markoCompiler.defaultOptions, options);
var writeToDisk = options.writeToDisk;
// If the template source is provided then we can compile the string
// in memory and there is no need to read template file from disk or
// write compiled code to disk.
//
// If writeToDisk is false then there will be no up-to-date check
// since compiled source won't be written to disk.
if ((templateSrc != null) || (writeToDisk === false)) {
// Don't write the compiled template to disk. Instead, load it
// directly from the compiled source using the internals of the
// Node.js module loading system.
if (templateSrc === undefined) {
templateSrc = fs.readFileSync(templatePath, fsOptions);
}
var compiledSrc = markoCompiler.compile(templateSrc, templatePath, options);
if (writeToDisk === true) {
var targetFile = templatePath + '.js';
fs.writeFileSync(targetFile, compiledSrc, fsOptions);
}
return loadSource(templatePath, compiledSrc);
var template;
if (typeof templatePath.render === 'function') {
template = templatePath;
} else {
return loadFile(templatePath, options);
}
};
var writeToDisk = options.writeToDisk;
module.exports.loadSource = loadSource;
// If the template source is provided then we can compile the string
// in memory and there is no need to read template file from disk or
// write compiled code to disk.
//
// If writeToDisk is false then there will be no up-to-date check
// since compiled source won't be written to disk.
if ((templateSrc != null) || (writeToDisk === false)) {
// Don't write the compiled template to disk. Instead, load it
// directly from the compiled source using the internals of the
// Node.js module loading system.
if (templateSrc == null) {
templateSrc = fs.readFileSync(templatePath, fsOptions);
}
var compiledSrc = markoCompiler.compile(templateSrc, templatePath, options);
if (writeToDisk === true) {
var targetFile = templatePath + '.js';
fs.writeFileSync(targetFile, compiledSrc, fsOptions);
}
template = loadSource(templatePath, compiledSrc);
} else {
template = loadFile(templatePath, options);
}
}
if (options.buffer != null) {
var Template = template.constructor;
template = new Template(
template.path,
createRenderProxy(template),
options);
}
return template;
}
require('../stream');

View File

@ -1,5 +1,4 @@
{
"main": "./html/index.js",
"browser": {
"./loader/index.js": "./loader/index-browser.js"
}

View File

@ -46,9 +46,5 @@ Readable.prototype = {
require('raptor-util/inherit')(Readable, stream.Readable);
require('./html').Template.prototype.stream = function(data) {
if (!stream) {
throw new Error('Module not found: stream');
}
return new Readable(this, data, this._options);
};

View File

@ -19,7 +19,6 @@
var markoVDOM = require('marko-vdom');
var commonHelpers = require('../helpers');
var extend = require('raptor-util/extend');
var runtime;
var classList = commonHelpers.cl;
@ -32,17 +31,6 @@ module.exports = extend({
return id + (i++);
};
},
/**
* Loads a template (__helpers.l --> marko_loadTemplate(path))
*/
l: function(path) {
if (typeof path === 'string') {
return runtime.load(path);
} else {
// Assume it is already a pre-loaded template
return path;
}
},
/**
* Helper for generating the string for a style attribute
@ -90,7 +78,7 @@ module.exports = extend({
} else {
return classList(classNames);
}
}
}, commonHelpers);
},
runtime = require('./');
i: require('./')._inline
}, commonHelpers);

View File

@ -1,32 +1,7 @@
/*
* Copyright 2011 eBay Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* This module provides the lightweight runtime for loading and rendering
* templates. The compilation is handled by code that is part of the
* [marko/compiler](https://github.com/raptorjs/marko/tree/master/compiler)
* module. If rendering a template on the client, only the runtime is needed
* on the client and not the compiler
*/
'use strict';
// helpers provide a core set of various utility methods
// that are available in every template
var helpers = require('./helpers');
var helpers;
/**
* Method is for internal usage only. This method
@ -34,24 +9,23 @@ var helpers = require('./helpers');
* it is used to create a new Template instance.
* @private
*/
exports.c = function createTemplate(path, createFunc) {
var template = new Template(path, lazyRender);
return template;
exports.c = function createTemplate(path, createFunc) {
var template = new Template(path, lazyRender);
return template;
function lazyRender() {
template._ = createFunc(helpers);
template._.apply(template, arguments);
}
};
function lazyRender() {
template._ = createFunc(helpers);
template._.apply(template, arguments);
}
};
var asyncVdomBuilder = require('async-vdom-builder');
var loader;
// If the optional "stream" module is available
// then Readable will be a readable stream
var AsyncVDOMBuilder = asyncVdomBuilder.AsyncVDOMBuilder;
function createOut(globalData) {
return new AsyncVDOMBuilder(globalData);
}
var extend = require('raptor-util/extend');
function renderCallback(renderFunc, data, globalData, callback) {
@ -72,9 +46,7 @@ function Template(path, func) {
}
Template.prototype = {
createOut() {
return new AsyncVDOMBuilder();
},
createOut: createOut,
renderSync: function(data) {
var localData;
var globalData;
@ -177,79 +149,11 @@ Template.prototype = {
}
};
function createRenderProxy(template) {
return function(data, out) {
template._(data, out);
};
}
function initTemplate(rawTemplate, templatePath) {
if (rawTemplate.render) {
return rawTemplate;
}
var createFunc = rawTemplate.create || rawTemplate;
var template = createFunc.loaded;
if (!template) {
template = createFunc.loaded = new Template(templatePath);
template.c(createFunc);
}
return template;
}
function load(templatePath, templateSrc, options) {
if (!templatePath) {
throw new Error('"templatePath" is required');
}
if (arguments.length === 1) {
// templateSrc and options not provided
} else if (arguments.length === 2) {
// see if second argument is templateSrc (a String)
// or options (an Object)
var lastArg = arguments[arguments.length - 1];
if (typeof lastArg !== 'string') {
options = arguments[1];
templateSrc = undefined;
}
} else if (arguments.length === 3) {
// assume function called according to function signature
} else {
throw new Error('Illegal arguments');
}
var template;
if (typeof templatePath === 'string') {
template = initTemplate(loader(templatePath, templateSrc, options), templatePath);
} else if (templatePath.render) {
template = templatePath;
} else {
template = initTemplate(templatePath);
}
if (options && (options.buffer != null)) {
template = new Template(
template.path,
createRenderProxy(template),
options);
}
return template;
}
function createInlineMarkoTemplate(filename, renderFunc) {
return new Template(filename, renderFunc);
}
exports.load = load;
exports.createOut = function() {
return new AsyncVDOMBuilder();
};
exports.helpers = helpers;
exports.createOut = createOut;
exports.Template = Template;
@ -263,8 +167,8 @@ exports.setDocument = function(newDoc) {
AsyncVDOMBuilder.prototype.document = newDoc;
};
// The loader is used to load templates that have not already been
// loaded and cached. On the server, the loader will use
// the compiler to compile the template and then load the generated
// module file using the Node.js module loader
loader = require('../loader');
helpers = require('./helpers');
exports.helpers = helpers;
require('../')._setRuntime(exports);

View File

@ -6,6 +6,7 @@ chai.config.includeStack = true;
var expect = require('chai').expect;
var path = require('path');
var marko = require('../');
var markoRuntimeHtml = require('../runtime/html');
var autotest = require('./autotest');
var fs = require('fs');
@ -41,7 +42,7 @@ describe('async-fragments (deprecated)', function() {
} else {
var template = marko.load(templatePath, loadOptions);
var templateData = main.templateData || {};
var out = marko.createWriter();
var out = markoRuntimeHtml.createWriter();
var events = [];
var eventsByFragmentName = {};

View File

@ -8,7 +8,9 @@ exports.check = function(marko, markoCompiler, expect, done) {
output += data;
});
var out = marko.createWriter(stream);
var runtimeHtml = require('marko/html');
var out = runtimeHtml.createWriter(stream);
out
.on('end', function() {
expect(output).to.equal('Hello John!');

View File

@ -1,7 +1,9 @@
var nodePath = require('path');
exports.check = function(marko, markoCompiler, expect, done) {
var out = marko.createWriter();
var runtimeHtml = require('marko/html');
var out = runtimeHtml.createWriter();
out
.on('finish', function() {
expect(out.getOutput()).to.equal('Hello John!');

View File

@ -6,4 +6,4 @@ function create(__markoHelpers) {
};
}
module.exports = require("marko").c(__filename, create);
module.exports = require("marko/html").c(__filename, create);

View File

@ -6,4 +6,4 @@ function create(__markoHelpers) {
};
}
module.exports = require("marko").c(__filename, create);
module.exports = require("marko/html").c(__filename, create);

View File

@ -6,4 +6,4 @@ function create(__markoHelpers) {
};
}
module.exports = require("marko").c(__filename, create);
module.exports = require("marko/html").c(__filename, create);

View File

@ -6,4 +6,4 @@ function create(__markoHelpers) {
};
}
module.exports = require("marko").c(__filename, create);
module.exports = require("marko/html").c(__filename, create);

View File

@ -10,4 +10,4 @@ function create(__markoHelpers) {
};
}
module.exports = require("marko").c(__filename, create);
module.exports = require("marko/html").c(__filename, create);

View File

@ -6,4 +6,4 @@ function create(__markoHelpers) {
};
}
module.exports = require("marko").c(__filename, create);
module.exports = require("marko/html").c(__filename, create);

View File

@ -9,4 +9,4 @@ function create(__markoHelpers) {
};
}
module.exports = require("marko").c(__filename, create);
module.exports = require("marko/html").c(__filename, create);

View File

@ -8,4 +8,4 @@ function create(__markoHelpers) {
};
}
module.exports = require("marko").c(__filename, create);
module.exports = require("marko/html").c(__filename, create);

View File

@ -20,4 +20,4 @@ function create(__markoHelpers) {
};
}
module.exports = require("marko").c(__filename, create);
module.exports = require("marko/html").c(__filename, create);

View File

@ -6,4 +6,4 @@ function create(__markoHelpers) {
};
}
module.exports = require("marko").c(__filename, create);
module.exports = require("marko/html").c(__filename, create);

View File

@ -6,4 +6,4 @@ function create(__markoHelpers) {
};
}
module.exports = require("marko").c(__filename, create);
module.exports = require("marko/html").c(__filename, create);

View File

@ -14,4 +14,4 @@ function create(__markoHelpers) {
};
}
module.exports = require("marko").c(__filename, create);
module.exports = require("marko/html").c(__filename, create);

View File

@ -20,4 +20,4 @@ function create(__markoHelpers) {
};
}
module.exports = require("marko").c(__filename, create);
module.exports = require("marko/html").c(__filename, create);

View File

@ -10,4 +10,4 @@ function create(__markoHelpers) {
};
}
module.exports = require("marko").c(__filename, create);
module.exports = require("marko/html").c(__filename, create);

View File

@ -17,4 +17,4 @@ function create(__markoHelpers) {
};
}
module.exports = require("marko").c(__filename, create);
module.exports = require("marko/html").c(__filename, create);

View File

@ -12,4 +12,4 @@ function create(__markoHelpers) {
};
}
module.exports = require("marko").c(__filename, create);
module.exports = require("marko/html").c(__filename, create);

View File

@ -23,4 +23,4 @@ function create(__markoHelpers) {
};
}
module.exports = require("marko").c(__filename, create);
module.exports = require("marko/html").c(__filename, create);

View File

@ -14,4 +14,4 @@ function create(__markoHelpers) {
};
}
module.exports = require("marko").c(__filename, create);
module.exports = require("marko/html").c(__filename, create);

View File

@ -9,4 +9,4 @@ function create(__markoHelpers) {
};
}
module.exports = require("marko").c(__filename, create);
module.exports = require("marko/html").c(__filename, create);

View File

@ -9,4 +9,4 @@ function create(__markoHelpers) {
};
}
module.exports = require("marko").c(__filename, create);
module.exports = require("marko/html").c(__filename, create);

View File

@ -4,4 +4,4 @@ function create(__markoHelpers) {
};
}
module.exports = require("marko").c(__filename, create);
module.exports = require("marko/html").c(__filename, create);

View File

@ -13,4 +13,4 @@ function create(__markoHelpers) {
};
}
module.exports = require("marko").c(__filename, create);
module.exports = require("marko/html").c(__filename, create);

View File

@ -6,4 +6,4 @@ function create(__markoHelpers) {
};
}
module.exports = require("marko").c(__filename, create);
module.exports = require("marko/html").c(__filename, create);

View File

@ -7,4 +7,4 @@ function create(__markoHelpers) {
};
}
module.exports = require("marko").c(__filename, create);
module.exports = require("marko/html").c(__filename, create);

View File

@ -6,4 +6,4 @@ function create(__markoHelpers) {
};
}
module.exports = require("marko").c(__filename, create);
module.exports = require("marko/html").c(__filename, create);

View File

@ -4,4 +4,4 @@ function create(__markoHelpers) {
};
}
module.exports = require("marko").c(__filename, create);
module.exports = require("marko/html").c(__filename, create);

View File

@ -27,4 +27,4 @@ function create(__markoHelpers) {
};
}
module.exports = require("marko").c(__filename, create);
module.exports = require("marko/html").c(__filename, create);

View File

@ -10,4 +10,4 @@ function create(__markoHelpers) {
};
}
module.exports = require("marko").c(__filename, create);
module.exports = require("marko/html").c(__filename, create);

View File

@ -25,4 +25,4 @@ function create(__markoHelpers) {
};
}
module.exports = require("marko").c(__filename, create);
module.exports = require("marko/html").c(__filename, create);

View File

@ -4,4 +4,4 @@ function create(__markoHelpers) {
};
}
module.exports = require("marko").c(__filename, create);
module.exports = require("marko/html").c(__filename, create);

View File

@ -37,4 +37,4 @@ function create(__markoHelpers) {
};
}
module.exports = require("marko").c(__filename, create);
module.exports = require("marko/html").c(__filename, create);

View File

@ -4,4 +4,4 @@ function create(__markoHelpers) {
};
}
module.exports = require("marko").c(__filename, create);
module.exports = require("marko/html").c(__filename, create);