Fixes #200 - Marko v3: Allow custom tag to be mapped to a template

This commit is contained in:
Patrick Steele-Idem 2016-01-10 17:26:10 -07:00
parent f45b1f364f
commit 15f2f18a28
11 changed files with 54 additions and 16 deletions

View File

@ -20,6 +20,24 @@ function getTaglibPath(taglibPath) {
}
}
function removeExt(filename) {
var ext = path.extname(filename);
if (ext) {
return filename.slice(0, 0 - ext.length);
} else {
return filename;
}
}
function requireResolve(builder, path) {
var requireResolveNode = builder.memberExpression(
builder.identifier('require'),
builder.identifier('resolve'));
return builder.functionCall(requireResolveNode, [ path ]);
}
class CompileContext {
constructor(src, filename, builder) {
ok(typeof src === 'string', '"src" string is required');
@ -241,6 +259,22 @@ class CompileContext {
return this._macros.registerMacro(name, params);
}
importTemplate(relativePath) {
ok(typeof relativePath === 'string', '"path" should be a string');
var builder = this.builder;
// We want to add the following import:
// var loadTemplate = __helpers.t;
// var template = loadTemplate(require.resolve(<templateRequirePath>))
var loadTemplateVar = this.addStaticVar('loadTemplate', '__helpers.l');
var requireResolveTemplate = requireResolve(builder, builder.literal(relativePath));
var loadFunctionCall = builder.functionCall(loadTemplateVar, [ requireResolveTemplate ]);
var templateVar = this.addStaticVar(removeExt(relativePath), loadFunctionCall);
return templateVar;
}
}
module.exports = CompileContext;

View File

@ -81,6 +81,7 @@ class CustomTag extends HtmlElement {
var context = codegen.context;
var tagDef = this.tagDef;
var inputProps = buildInputProps(this, context);
var rendererPath = tagDef.renderer;
if (rendererPath) {
@ -89,10 +90,16 @@ class CustomTag extends HtmlElement {
let loadRendererFunctionCall = builder.functionCall(loadRendererVar, [ requireRendererFunctionCall ]);
let rendererVar = codegen.addStaticVar(removeExt(rendererPath), loadRendererFunctionCall);
var inputProps = buildInputProps(this, context);
var tagArgs = [ 'out', rendererVar, inputProps ];
var tagFunctionCall = builder.functionCall(tagVar, tagArgs);
let tagArgs = [ 'out', rendererVar, inputProps ];
let tagFunctionCall = builder.functionCall(tagVar, tagArgs);
return tagFunctionCall;
} else if (tagDef.template) {
let templateRequirePath = context.getRequirePath(tagDef.template);
let templateVar = context.importTemplate(templateRequirePath);
let renderMethod = builder.memberExpression(templateVar, builder.identifier('render'));
let renderArgs = [ inputProps, 'out' ];
let renderFunctionCall = builder.functionCall(renderMethod, renderArgs);
return renderFunctionCall;
}
}
}

View File

@ -187,19 +187,12 @@ module.exports = {
/**
* Loads a template
*/
l: function(path, req) {
l: function(path) {
if (typeof path === 'string') {
if (path.charAt(0) === '.' && req.resolve) { // Check if the path is relative
// The path is relative so use require.resolve to fully resolve the path
path = req.resolve(path);
}
return runtime.load(path);
} else if (path.render) {
} else {
// Assume it is already a pre-loaded template
return path;
} else {
return runtime.load(path);
}
},
/**

View File

@ -18,5 +18,6 @@
}
},
"<test-hello>": "taglib/test-hello/marko-tag.json",
"<test-template-as-tag>": "taglib/test-template-as-tag/marko-tag.json",
"tags-dir": "./taglib/scanned-tags"
}

View File

@ -1 +0,0 @@
<div><h1>My Page Title</h1></div>

View File

@ -1,3 +0,0 @@
<div>
<test-page-title title="My Page Title"/>
</div>

View File

@ -0,0 +1 @@
Hello Frank!

View File

@ -0,0 +1 @@
<test-template-as-tag name="Frank"/>

View File

@ -0,0 +1,4 @@
{
"template": "./template.marko",
"@name": "string"
}

View File

@ -0,0 +1 @@
Hello ${data.name}!