diff --git a/compiler/CompileContext.js b/compiler/CompileContext.js index 1950d51f5..7309cbefa 100644 --- a/compiler/CompileContext.js +++ b/compiler/CompileContext.js @@ -510,9 +510,17 @@ class CompileContext extends EventEmitter { var builder = this.builder; varName = varName || removeExt(path.basename(relativePath)) + '_template'; - var requireResolveTemplate = requireResolve(builder, builder.literal(relativePath)); - var loadFunctionCall = builder.functionCall(this.helper('loadTemplate'), [ requireResolveTemplate ]); - var templateVar = this.addStaticVar(varName, loadFunctionCall); + var templateVar; + + if (this.options.browser) { + // When compiling a Marko template for the browser we just use `require('./template.marko')` + templateVar = this.addStaticVar(varName, builder.require(builder.literal(relativePath))); + } else { + // When compiling a Marko template for the server we just use `loadTemplate(require.resolve('./template.marko'))` + let loadTemplateArg = requireResolve(builder, builder.literal(relativePath)); + let loadFunctionCall = builder.functionCall(this.helper('loadTemplate'), [ loadTemplateArg ]); + templateVar = this.addStaticVar(varName, loadFunctionCall); + } this.pushMeta('tags', builder.literal(relativePath), true); diff --git a/compiler/index.js b/compiler/index.js index 585facf28..2f5407249 100644 --- a/compiler/index.js +++ b/compiler/index.js @@ -106,7 +106,7 @@ function compileForBrowser(src, filename, options, callback) { options = null; } - options = extend({output: 'vdom'}, options); + options = extend({output: 'vdom', browser: true}, options); return compile(src, filename, options, callback); } @@ -139,7 +139,7 @@ function compileFileForBrowser(filename, options, callback) { options = null; } - options = extend({output: 'vdom'}, options); + options = extend({output: 'vdom', browser: true}, options); return compileFile(filename, options, callback); } diff --git a/test/autotests/compiler-browser/include/expected.js b/test/autotests/compiler-browser/include/expected.js new file mode 100644 index 000000000..afbc572cb --- /dev/null +++ b/test/autotests/compiler-browser/include/expected.js @@ -0,0 +1,14 @@ +var marko_template = module.exports = require("marko/vdom").t(__filename), + include_target_template = require("./include-target.marko"), + marko_helpers = require("marko/runtime/vdom/helpers"), + marko_loadTag = marko_helpers.t, + include_tag = marko_loadTag(require("marko/taglibs/core/include-tag")); + +function render(data, out) { + include_tag({ + _target: include_target_template, + foo: "bar" + }, out); +} + +marko_template._ = render; diff --git a/test/autotests/compiler-browser/include/include-target.marko b/test/autotests/compiler-browser/include/include-target.marko new file mode 100644 index 000000000..e69de29bb diff --git a/test/autotests/compiler-browser/include/template.marko b/test/autotests/compiler-browser/include/template.marko new file mode 100644 index 000000000..6a87e26eb --- /dev/null +++ b/test/autotests/compiler-browser/include/template.marko @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/test/autotests/compiler-browser/simple/expected.js b/test/autotests/compiler-browser/simple/expected.js new file mode 100644 index 000000000..e743a8546 --- /dev/null +++ b/test/autotests/compiler-browser/simple/expected.js @@ -0,0 +1,44 @@ +var marko_template = module.exports = require("marko/vdom").t(__filename), + marko_helpers = require("marko/runtime/vdom/helpers"), + marko_forEach = marko_helpers.f, + marko_createElement = marko_helpers.e, + marko_const = marko_helpers.const, + marko_const_nextId = marko_const("6597f2"), + marko_node0 = marko_createElement("div", null, 1, marko_const_nextId()) + .t("No colors!"); + +function render(data, out) { + out.t("Hello "); + + out.t(data.name); + + out.t("! "); + + if (data.colors.length) { + out.be("ul"); + + marko_forEach(data.colors, function(color) { + out.e("li", null, 1) + .t(color); + }); + + out.ee(); + } else { + out.n(marko_node0); + } + + if (data.colors.length) { + out.be("ul"); + + marko_forEach(data.colors, function(color) { + out.e("li", null, 1) + .t(color); + }); + + out.ee(); + } else { + out.n(marko_node0); + } +} + +marko_template._ = render; diff --git a/test/autotests/compiler-browser/simple/template.marko b/test/autotests/compiler-browser/simple/template.marko new file mode 100644 index 000000000..8c83d767c --- /dev/null +++ b/test/autotests/compiler-browser/simple/template.marko @@ -0,0 +1,27 @@ +--- +Hello ${data.name}! + + +
+ No colors! +
+ + + + + +
+ No colors! +
+
+--- \ No newline at end of file diff --git a/test/compiler-browser-test.js b/test/compiler-browser-test.js new file mode 100644 index 000000000..a4c4fd94b --- /dev/null +++ b/test/compiler-browser-test.js @@ -0,0 +1,52 @@ +'use strict'; +require('./util/patch-module'); + +var chai = require('chai'); +chai.config.includeStack = true; +var path = require('path'); +var compiler = require('../compiler'); +var autotest = require('./autotest'); +var fs = require('fs'); + +require('marko/node-require').install(); + +describe('compiler (browser target)', function() { + var autoTestDir = path.join(__dirname, 'autotests/compiler-browser'); + + autotest.scanDir(autoTestDir, function run(dir, helpers, done) { + var templatePath = path.join(dir, 'template.marko'); + var mainPath = path.join(dir, 'test.js'); + var main; + + if (fs.existsSync(mainPath)) { + main = require(mainPath); + } + + if (main && main.checkError) { + var e; + + try { + compiler.compileFileForBrowser(templatePath); + } catch(_e) { + e = _e; + } + + if (!e) { + throw new Error('Error expected'); + } + + main.checkError(e); + done(); + + } else if (main && main.checkTemplate) { + var template = require('marko').load(templatePath, main.compilerOptions); + main.checkTemplate(template); + done(); + } else { + var compiledSrc = compiler.compileFileForBrowser(templatePath, main && main.compilerOptions); + helpers.compare(compiledSrc, '.js'); + done(); + } + }); + +}); \ No newline at end of file diff --git a/widgets/browser.json b/widgets/browser.json index 7a363aa01..3f0482ba4 100644 --- a/widgets/browser.json +++ b/widgets/browser.json @@ -6,5 +6,11 @@ "run": true, "if": "!flags.contains('marko-widgets/no-client-init')" } + ], + "requireRemap": [ + { + "from": "./loadWidget.js", + "to": "./loadWidget-dynamic.js" + } ] } \ No newline at end of file diff --git a/widgets/loadWidget-dynamic.js b/widgets/loadWidget-dynamic.js new file mode 100644 index 000000000..7cc3e1325 --- /dev/null +++ b/widgets/loadWidget-dynamic.js @@ -0,0 +1,8 @@ +'use strict'; + +module.exports = function load(typeName) { + // We make the assumption that the widget type name is a path to a + // fully resolved module path and that the module exists + // as a CommonJS module + return require(typeName); +}; \ No newline at end of file diff --git a/widgets/loadWidget.js b/widgets/loadWidget.js new file mode 100644 index 000000000..ada1c0086 --- /dev/null +++ b/widgets/loadWidget.js @@ -0,0 +1,4 @@ +'use strict'; +module.exports = function load(typeName) { + throw new Error('Unable to load: ' + typeName); +}; \ No newline at end of file diff --git a/widgets/registry.js b/widgets/registry.js index d69282f57..c449ad49a 100644 --- a/widgets/registry.js +++ b/widgets/registry.js @@ -1,3 +1,5 @@ +var loadWidget = require('./loadWidget'); + var registered = {}; var loaded = {}; var widgetTypes = {}; @@ -27,7 +29,7 @@ function load(typeName) { target = target(); } if (!target) { - target = require(typeName); // Assume the typeName has been fully resolved already + target = loadWidget(typeName); // Assume the typeName has been fully resolved already } loaded[typeName] = target || null; }