marko-js / marko

A declarative, HTML-based language that makes building web apps fun
https://markojs.com/
MIT License
13.37k stars 644 forks source link

Create template from string #74

Closed yazla closed 9 years ago

yazla commented 9 years ago

I didn't get how is it possible to render a template from string. Is it possible at all?

Thanks.

philidem commented 9 years ago

Try this:

var markoCompiler = require('marko/compiler');
markoCompiler.compile(templateStr, templatePath, function(err, compiledCode) {
    if (err) {
        return callback(err);
    }
    // handle compiledCode here
});

The templatePath argument is used for resolving taglibs/includes and error reporting; there doesn't actually have to be a template file at this path.

Let me know if that works for you and I can close this issue.

yazla commented 9 years ago

Doesn't work in browser using browserify. I am getting require.resolve is not a function on

exports.taglibs.registerTaglib(require.resolve("../taglibs/core/marko-taglib.json"));

philidem commented 9 years ago

The "Try Online" section of the raptorjs website does client-side compilation of Marko templates: http://raptorjs.org/marko/try-online/

The client code that does the compiling is here: https://github.com/raptorjs/website/blob/master/src/components/app-marko-try-online/widget.js

This uses Lasso (formerly named "Optimizer") instead of Browserify.

Is not possible to pre-compile your templates during build or on server-side? This would be the most efficient way to compile templates.

yazla commented 9 years ago

Thanks for the directions, but I have already switched to another template engine, too much hassle for such a simple thing. As for me marko.load should be able to work with a raw template string or there should be any other method do this job in one line as it is in the most of the template engines. Anyway thanks for your help.

patrick-steele-idem commented 9 years ago

Hi @yazla, it's almost always a bad idea to compile a template in the browser with any template engine (compilation is relatively slow and sending the compiler to the browser introduces a lot of extra overhead). The Marko compiler is designed to run on the server in a Node.js environment where it can access the file system and have access to other taglibs installed via npm. Sorry Marko didn't work out for you, but I think you should reconsider compiling templates in the browser.

Just to be clear, if you do what is suggested in the docs and enable the markoify transform for browserify then the compiled template will automatically be sent down to the browser and your code to render templates will just work. Please see the Using Browserify section in the docs. Let us know if you still have questions.

yazla commented 9 years ago

@patrick-steele-idem of course I agree with you. But I bet you will not notice a difference in case of simple templates between precompiled and compiled in browser. I am actually doing a simple Chrome extension and don't need 60 fps. Another thing is that usually you want to make it workable asap and after that do the optimizations so it is usually very handy to just have a single method for a single render operation to see it right away.

patrick-steele-idem commented 9 years ago

@yazla, I see where you are coming from, but I still don't see why it is any different to bundle up the compiled templates versus the uncompiled templates. The compiled template is just a standard CommonJS module that exports a function that can be used to load a Template instance. For example:

var template = require('marko').load(require('./my-template.marko.js'));

The above code works if the template has already been compiled (i.e. the *.marko.js file already exists). In the case where the template is not compiled the markoify transform will do that for you automatically if the code to load your template is in the following form:

var template = require('marko').load(require.resolve('./my-template.marko'));

If it helps, you can use the markoc command line compiler to compile all of your templates to CommonJS modules beforehand. For example, to compile all templates in the current directory and all sub directories:

npm install marko --global
markoc .

I hope that helps.

tonii75 commented 9 years ago

Hi, I'd like to add a use case for client compilation. We're currently not using nodejs on the server (but a CMS system) and would like our users to add their own custom templates to a "templates library". We don't mind if this means a second or two delay compiling the template before its pushed to the library. These templates are then used in the main app. Unfortunately at the moment it seems templates have to be pushed by the development team with access to a node environment.

patrick-steele-idem commented 9 years ago

Hi @tonii75, the compiler does work in the browser but it does require that you use the Lasso.js module runtime in the browser since the Browserify module runtime doesn't support dynamic requires. For the "Try Marko Online" feature we are using the compiler in the browser. Here's the relevant code: https://github.com/marko-js/markojs.com/blob/master/src/components/app-try-marko/index.js

I hope that helps. If you want to discuss further might be better to open a new Github issue.

allanchau commented 6 years ago

@philidem Hi, I'm looking to do a similar thing and render a template from a string (server side). Once I have compiled the string using the code you posted above, how do I then get the HTML from that?

The compiled string is // Compiled using marko@4.4.26 - DO NOT EDIT\n"use strict";\n\nvar marko_template = module.exports = require("marko/dist/html").t(__filename);\n\nfunction render(input, out) {\n var data = input;\n\n if (user.addressCountry === "Australia") {\n out.w("Correct");\n }\n}\n\nmarko_template._ = render;\n\nmarko_template.meta = {};\n and I am looking to get the text Correct

Thanks