Code Monkey home page Code Monkey logo

mu's Introduction

Mu - a fast, streaming Node.js Mustache engine

Warning: This version is not API compatible with 0.1.

Install

I have had some issues with my npm auth and got it in a bit of a rut, so for now you have to:

npm install mu2

Issues

Currently mu does not support changing the tag form ({{ }} to say <% %>).

Usage

There are a few ways to use mu 0.5. Here is the simplest:

var mu = require('mu2'); // notice the "2" which matches the npm repo, sorry..

mu.root = __dirname + '/templates'
mu.compileAndRender('index.html', {name: "john"})
  .on('data', function (data) {
    console.log(data.toString());
  });

Here is an example mixing it with the http module:

var http = require('http')
  , util = require('util')
  , mu   = require('mu2');

mu.root = __dirname + '/templates';

  http.createServer(function (req, res) {

  var stream = mu.compileAndRender('index.html', {name: "john"});
  stream.pipe(res);

}).listen(8000);

Taking that last example here is a little trick to always compile the templates in development mode (so the changes are immediately reflected).

var http = require('http')
  , util = require('util')
  , mu   = require('mu2');

mu.root = __dirname + '/templates';

http.createServer(function (req, res) {

  if (process.env.NODE_ENV == 'DEVELOPMENT') {
    mu.clearCache();
  }

  var stream = mu.compileAndRender('index.html', {name: "john"});
  util.pump(stream, res);

}).listen(8000);

API

mu.root

  A path to lookup templates from. Defaults to the working directory.


mu.compileAndRender(String templateName, Object view)

  Returns: Stream

  The first time this function is called with a specific template name, the
  template will be compiled and then rendered to the stream. Subsequent
  calls with the same template name will use a cached version of the compiled
  template to improve performance (a lot).


mu.compile(filename, callback)

  Returns nil
  Callback (Error err, Any CompiledTemplate)

  This function is used to compile a template. Usually you will not use it
  directly but when doing wierd things, this might work for you. Does not
  use the internal cache when called multiple times, though it does add the
  compiled form to the cache.


mu.compileText(String name, String template, Function callback)

  Returns nil
  Callback (err, CompiledTemplate)

  Similar to mu.compile except it taks in a name and the actual string of the
  template. Does not do disk io. Does not auto-compile partials either.


mu.render(Mixed filenameOrCompiledTemplate, Object view)

  Returns Stream

  The brother of mu.compile. This function takes either a name of a template
  previously compiled (in the cache) or the result of the mu.compile step.

  This function is responsible for transforming the compiled template into the
  proper output give the input view data.


mu.renderText(String template, Object view, Object partials)

  Returns Stream

  Like render, except takes a template as a string and an object for the partials.
  This is not a very performant way to use mu, so only use this for dev/testing.


mu.clearCache(String templateNameOrNull)

  Clears the cache for a specific template. If the name is omitted, clears all cache.

mu's People

Contributors

deestan avatar diegossilveira avatar farvilain avatar nemtsov avatar oleics avatar pdehaan avatar pfleidi avatar raycmorgan avatar raymorgan avatar sammerry avatar shawnfeldman avatar ulikoehler avatar zubairov avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mu's Issues

How to output error code instead of missing partial?

Hi, I'm trying to listen on output stream for error message and then emit it as data, but it doesn't work โ€” the request hangs up and never returns. I need to output error message instead of missing partial, and keep all the rest blocks rendered.

Is there a way to solve my problem?

pageData = ""
pageStream = mu.compileAndRender fileName

pageStream.on "data", (data) ->
  pageData += data

pageStream.on "end", ->
  stream = mu.compileAndRender "layout.html", {page: pageData}
  util.pump stream, response

pageStream.on "error", (err) ->
  pageStream.emit 'data', err.message
  # pageStream.emit 'end'

Double quotes (") char is not escaped properly if partials involved

Adding a HTML nodes some string parameter with double quotes will crash the compilation on the "eval" ( lib/compiler.js @ 24 line ) of the generated template function.

Besides there are some tests (complex.html.mu) with the ["]-s inside, they doesn't trigger exception and ["] are escaped properly. It seems the issue is caused by partials. If you remove ["] from inner_partial.html.mu in example below, the top-level ["]-s in partial.html.mu are magically correct escaped.

There is a dirty workaround: just use sinlge quotes (') for the parameters in templates and all will be good.

This case (with params in tags in partial) seems needs to be checked in tests. Plus some try-catch block for the "eval" would not hurt anyone.

in partial.html.mu

{{title}}


{{>inner_partial.html}}

in inner_partial.html.mu

Again, {{title}}!

Will produce this code for the template-function:

(function COMPILED(context, options) {
    options = options || {};
    var Mu = M;
    var REE = new RenderEventEmitter(options);
    process.nextTick(function () {
        REE.write("<h1>First: ");
        REE.write(Mu.escape(Mu.normalize(context, "title")));
        REE.write("</h1>");
        REE.write("\n");
        REE.write("<h1 class="header">"); //<-- not good here, will cause exception...
        REE.write(Mu.escape(Mu.normalize(context, "title")));
        REE.write("</h1>");
        REE.write("\n");
        REE.write("<div class="title">Again, "); // <-- and here
        REE.write(Mu.escape(Mu.normalize(context, "title")));
        REE.write("!</div>");
        REE.write("\n");
        REE.write("\n");
        REE.close();
    });
    return REE;
})

{{.}} not working

maybe i missed it, but when iterating through a simple array like [1, 2, 3, 4], shouldn't {{.}} indicate the current item? how to handle unnamed items?

data -> body, eof -> complete?

My first impression is that this looks pretty cool. I'm wondering if you think it would be good to make the event types emitted more in line with what Node emits:

The data event would become a body event
The eof event would become a complete event

breaks with node v0.1.96-27-gb480184

node> var mu = kiwi.require('mu', '0.0.1')
Error: process.mixin() has been removed.
at EventEmitter.mixin (node.js:11:11)
at Object. (/Users/bitzesty/.kiwi/current/seeds/mu/0.0.1/lib/mu/compiler.js:76:9)
at Module._compile (module:384:23)
at Module._loadScriptSync (module:393:16)
at Module.loadSync (module:296:10)
at loadModule (module:241:16)
at require (module:364:12)
at Object. (/Users/bitzesty/.kiwi/current/seeds/mu/0.0.1/lib/mu.js:8:19)
at Module._compile (module:384:23)
at Module._loadScriptSync (module:393:16)

Compile a string rather than a file?

Can we do this? If not I would love to see this made possible!

EDIT: OK looking at the source, it is possible using a combination of parser.js and compiler.js.

Would be exceptional if you exposed a direct API however! I could make a patch if your time is limited.

Get Templates

Hey,

Is there a way to just get the template informations mu2 uses? Just resolve the partials and don't render any data to the template (and don't replace other mustache tags except partials)

Use case: Use the same templates on client and server. I have to find a way to deliver a partial free version of the templates to the client.

Support for dot notation

Mu2 does not seem to support dot notation. It does not crash, but it does not seem to output the value of the variable:

{{object.property}}

Missing 'return' in mu.js

Missing return at line 34 in mu.js (0.5.13):

if (err) {
  callback(new Error('file_not_found'));//errors.fileNotFound(mu.root, filename, err)));
}

when file isn't present:

.../node_modules/mu2/lib/mu/parser.js:15
this.template = template.replace(/\r\n/g, carriage)
^
TypeError: Cannot call method 'replace' of undefined
at Object.Parser (.../node_modules/mu2/lib/mu/parser.js:15:28)
at Object.parse (.../node_modules/mu2/lib/mu/parser.js:10:16)
at .../node_modules/mu2/lib/mu.js:37:21
at [object Object]. (fs.js:88:5)
at [object Object].emit (events.js:67:17)
at Object.oncomplete (fs.js:1058:12)

Non-false value sections don't render

Template:
{{#person?}}
Hi {{name}}!
{{/person?}}

Hash:
{
"person?": { "name": "Jon" }
}

Result:

Hi!

This also seems to be the case on the mustach demo site :(

Write output to file

Is there anyway to write the output of mu.compileAndRender to a html file?

Ive been trying with fs.writefile and all I get is partially formatted html with broken tags.

Memory leak due to infinite loop in recursive partials.

Hey, I was using mu to render posts, and posts had a "replies" array that also contained posts. So my post.html looked something like

{{#post}}
<div class="post" id="post_{{id}}">
  <div class="message">{{message}}</div>
  <div class="replies">
    {{#replies}} {{>post.html}} {{/replies}}
  </div>
</div>
{{/post}}

Then in some file I tried to render some posts by calling {{> post.html}} which then made my CPU spike and node to take up like a gig of RAM in a few seconds.

Curiously, when I had refreshed my page, the rendering had become instantaneous and the RAM usage was increasing at the same speed at before.

My conclusion from this is that Mu entered an infinite loop while trying to compile post.html into a template because when it got to the code with {{> post.html}}, the template hadn't been compiled yet so it was being fetched from memory and compiled, which just kept on happening.

I haven't looked into the code, but I'm guessing you can remove the check for a template being compiled at compile time, and leave that check for when something is actually being rendered.

Rendered data doesn't write correctly to HTTP stream.

I'm finding that writing data to a HTTP response stream stops after the first replacement.

This is the code to replicate:

var http = require('http');
var mu = require("mu2");

http.createServer(function(req, res) {
    mu.clearCache("helloMsg");
    mu.compileText("helloMsg", "<p>Hello, {{name}}.</p>");
    mu.render("helloMsg", {name: "John"}).on('data', function(data) {
        var asString = data.toString();
        console.log(asString);
        res.write("<body>"+asString+"</body>");
        res.end();
    });
}).listen(8888);

HTTP output (note that ".

" has been stripped):

<body><p>Hello, </body>

Console output:

<p>Hello,
John
.</p>

I'm using Node.js v0.10.5 on Linux Mint and mu2 is reported as version 0.5.17.

Dynamic text surrounded by new lines

I've noticed that the text output will append new lines to the start and end of the text being replaced.

Here is a simple script:

var mu = require('mu2');

mu.root = __dirname + '/templates';
mu.compileAndRender('test.html', {name: 'John'})
    .on('data', function (data) {
        console.log(data.toString());
    });

templates/test.html is:

<h1>Hello {{name}}</h1>

The output is:

<h1>Hello 
John
</h1>

instead of:

<h1>Hello John</h1>

I'm using node v0.8.4 and tried with both npm and github versions of mu2.

"template not in cache" error

Hi,

I get the following error trying to use the demo code with express:

Error: template_not_in_cache
at Object.render (/usr/local/lib/node/.npm/mu/0.5.1/package/lib/mu.js:110:11)
at Object. (/Volumes/Docs/Node/sppericat/server.js:17:5)
at param (/usr/local/lib/node/.npm/connect/1.3.0/package/lib/middleware/router.js:148:21)
at pass (/usr/local/lib/node/.npm/connect/1.3.0/package/lib/middleware/router.js:164:10)
at Object.router as handle
at next (/usr/local/lib/node/.npm/connect/1.3.0/package/lib/http.js:204:15)
at Object.handle (/usr/local/lib/node/.npm/express/2.2.1/package/lib/http.js:75:5)
at next (/usr/local/lib/node/.npm/connect/1.3.0/package/lib/http.js:204:15)
at HTTPServer.handle (/usr/local/lib/node/.npm/connect/1.3.0/package/lib/http.js:217:3)
at HTTPServer.emit (events.js:67:17)

Cheers,
Stephane

Cannot render multiple templates

Would real like to be able to render nested templates. This would allow me to break my html up into reusable parts rather than duplication code every where. My thought would be to enable renders to be passed as part of the view. Something like this:

var stream = mu.compileAndRender('index.mu', {
    header: mu.compileAndRender('header.mu', {
        title:'Home page'
    });
});

If tag is not specified..

..it fails. I tried with a tpl containing {{mytag}} and a json shema {john:"I'm john"}, I got no response from the server (I use the example mentioned on the main page).
It seems simple to correct, but that really harm (I mean if I forget only one string the client never get the data). Would be better if {{mytag}} would be replaced by a blank if not found :) (throwing an error in the server, but not blocking evthg)

Ciao,
Jk.

Mu seems stall event loop

Hello. I've wrote simple benchmark (http://github.com/mbeloshitsky/Mu/blob/master/benchmarks/blocking.js) to check how Mu templating deals with event loop and get following results:

*** Mu templating
   Ticks: 2
   Time: 643ms
*** Idle time
   Ticks: 429437
   Time: 644ms

Seems that mu in it's synchronous version (asynchronous probably too but i've not tested it) stalls event loop while rendering template. Possible solution is inject nextTick somewhere in rendering process.

Default file extension

It'd be nice if we could specify a default file extension so that we could reference "foo.html" as just {{> foo}} instead of {{> foo.html}}, just to make the templates a little cleaner. Also, maybe use that for the render and compile functions as well.

request for docs

It would be much faster to figure out how to hook up Mu with Express if there existed a sample app or any kind of tips. I get the impression from previous (now closed) issues related to Express that it is possible to make it work, but the conversation is in shorthand that assumes much better Express and Mu skills than mine. This is where documentation usually comes in.

No lambda support

The code fragment below is a copy from mustache, but I can't get render object defined for lambda support. The console told me argument render is undefined. Is there something that i misunderstand?

Template:

{{#wrapped}}
     {{name}} is awesome.
{{/wrapped}}

Hash:

{
  "name": "Willy",
    "wrapped": function() {
     return function(text, render) { //render param is undefined
       return "<b>" + render(text) + "<b/>"
    }
  }
}

Integration with express

I've recently integrated Mu with express as the default templating engine for HTML files. I used the following module to achieve it:

var mu = require('mu2');

exports.__express = function (path, options, callback) {

    var result = '';

    var stream = mu.compileAndRender(path, options)
    .on('data', function (data) {
        result += data.toString();
    })
    .on('end', function () {
        callback(null, result);
    });

}

I wonder if you'd consider integrating something like the above into Mu? It needs a little more work, because you should be able to control caching within the options handle which I haven't wired up. But the above code works along with the following to integrate it into express:

app.set('views', __dirname + '/layouts');   // tell express where my views are
app.engine('html', muexpress.__express);    // register the mu templating engine (using my mu-express gateway)
app.set('view engine', 'html');             // register the default template engine as html

If you integrate it, I'd be keen to add a patch to https://github.com/visionmedia/consolidate.js/ so that you can use Mu with express quite simply.

Let me know your thoughts. I'd be happy to integrate it into Mu myself and send through a pull request.

cheers,
Scott.

Using partials

I think it's worth noting somewhere in your Readme that, in order to be able to use partials, you must configure mu.root, like so:

var mu = require('mu');
var path = require('path');

mu.root = path.join(__dirname, 'server/views');

Assuming you were storing your views in the folder server/views relative to the main app.js file. There doesn't appear to be a way to call a partial like so

{{>server/views/header.mu}}

So, the definition, I presume, directs Mu where to look for

{{>header.mu}}

Asynchronous lambda support

Consider adding asynchronous lambda support? It would work as follows:

  • Function values would support an optional callback argument.
  • Function values accepting the callback would return an undefined value and pass the template value at a later stage using the callback.
  • Function values will continue to work synchronously if they returning a value.

The solution would look like this:

var data = {
    value: function( body, cb ) {
        process.nextTick(function() {
            cb('result');
        });
    }
}

I've implemented a solution here: juliangoacher@599ea69

The solution will inspect the arity of a value function to try and avoid the situation where a function which doesn't accept the callback returns undefined and so hangs the process.

demo.js fails

C:\Program Files\nodejs\sites\examples\Mu>node demo
The "sys" module is now called "util". It should have a similar interface.
Outputting examples/simple.html.mu with a chunkSize of 10


node.js:201
        throw e; // process.nextTick error, or 'error' event on first tick
          ^
SyntaxError: Unexpected token ILLEGAL
    at Object.compile (C:\Program Files\nodejs\sites\examples\Mu\lib\mu\compiler.js:23:19)
    at C:\Program Files\nodejs\sites\examples\Mu\lib\mu.js:50:36
    at C:\Program Files\nodejs\sites\examples\Mu\lib\mu\parser.js:22:9
    at Array.0 (C:\Program Files\nodejs\sites\examples\Mu\lib\mu\preprocessor.js:24:14) at EventEmitter._tickCallback (node.js:192:40)`

feature request: expose render context

One of the rather nice features of janl's implementation of Mustache in JS is that the context is exposed, so it can be overwritten in order to provide certain filters/defaults/features.

It can be exposed quite easily by changing function walkToFind(context, name) in render.js to render.context = function(context, name).

I would really like to see this in Mu. Thank you for your time.

partials with mu-cli.js

hey guys, I was playing with mu-cli.js and couldn't make partials work...

partial.html

<h1>yo-ho-ho</h1>

template.html

<html>
  <body>
    {{> partial}}
  </body>
</html>

command:

cat template.html | node_modules/mu2/lib/mu-cli.js --view={}

output:

<html>
  <body>

  </body>
</html>

desired output:

<html>
  <body>
    <h1>yo-ho-ho</h1>
  </body>
</html>

am I doing something wrong?

eval(code) in compiler fails

I tried to run the following code:

mu.render("index.html", {host: IOHOST}, {}, function(err, buffer) {httphelper.sendHTML(res, 200, buffer)})

Then "err" has the following error: "SyntaxError: Unexpected identifier"

It fails in compiler.js at "var func = eval(code);" with code:

(function COMPILED(context, options) {
options = options || {};
var Mu = M;
var REE = new RenderEventEmitter(options);
process.nextTick(function () {
REE.write(Mu.escape(Mu.normalize(context, "host")));
REE.close();
});
return REE;
})

I checked that the template file is read correctly, I tried the example, also fails.
I use the latest NodeJS (1.92) and Mu.

Mu fails when using new lines and HTML tags

Example:

Working:

<b>{{foo}}</b>

Fails:

<b>
{{foo}}
</b>

Exception:

/node_modules/mu2/lib/mu/parser.js:95
      throw new Error('Encountered an unclosed tag: "' + this.otag + this.buff
            ^
__MU_NEWLINE__</b>"an unclosed tag: "{{foo}}
    at Object.scanTag (/node_modules/mu2/lib/mu/parser.js:95:13)
    at Object.tokenize (/node_modules/mu2/lib/mu/parser.js:29:56)
    at Object.parse (/node_modules/mu2/lib/mu/parser.js:9:17)
    at /node_modules/mu2/lib/mu.js:37:21
    at [object Object].<anonymous> (fs.js:115:5)
    at [object Object].emit (events.js:64:17)
    at afterRead (fs.js:1117:12)
    at Object.wrapper [as oncomplete] (fs.js:254:17)

When looking in your examples there are no examples where you use newlines when working with tags, but I think this is a normal usage of HTML?

License missing

It seems both the repository and package.json are missing license information. I assume this is under MIT license, like most of Node.js modules, but obviously this can't be taken for granted

Getting errors with repeated sections.

Using the v2 branch (npm default) I'm getting errors when simply just repeating sections. E.g.

{{#user}}
Hi {{name}}!
{{/user}}
...
{{#user}}
Bye {{name}}
{{/user}}

If user is found, this yields:

Error: Cyclic proto value
at insertProto (/usr/local/lib/node/.npm/mu/0.5.2/package/lib/mu/renderer.js:174:17)
at section (/usr/local/lib/node/.npm/mu/0.5.2/package/lib/mu/renderer.js:137:17)
at next (/usr/local/lib/node/.npm/mu/0.5.2/package/lib/mu/renderer.js:53:20)
at next (/usr/local/lib/node/.npm/mu/0.5.2/package/lib/mu/renderer.js:38:16)
at next (/usr/local/lib/node/.npm/mu/0.5.2/package/lib/mu/renderer.js:32:27)
at next (/usr/local/lib/node/.npm/mu/0.5.2/package/lib/mu/renderer.js:38:16)
at next (/usr/local/lib/node/.npm/mu/0.5.2/package/lib/mu/renderer.js:48:18)
at next (/usr/local/lib/node/.npm/mu/0.5.2/package/lib/mu/renderer.js:38:16)
at render (/usr/local/lib/node/.npm/mu/0.5.2/package/lib/mu/renderer.js:84:3)
at section (/usr/local/lib/node/.npm/mu/0.5.2/package/lib/mu/renderer.js:138:5)

"Error" event not being sent;

I'm using Mu2 with express for my rendering, and for some reason it's outright crashing whenever there's an error instead of emitting an "error" event on the stream. Here's the code I'm using:

var stream = mu.compileAndRender(name, local);
stream.pipe(res);
stream.on("error",function(err){
    res.send(err);
})

The error I was getting was:

C:\Users\.....\node_modules\mu2\lib\mu\parser.js:36
      throw new Error('Encountered an unclosed section.');

Which I have since fixed. But I'd prefer things to fail more graceful whereas my server is currently just crashing whenever I have an error.

Any help would be much appreciated.

Dynamic partials support

Not sure if this is a moustache issue, node.js issue or Mu2 issue.

I'm using partials to include templates. For example:

home.mu

 <p1>Welcome {{person}}</p1>

page.mu

<html>
    {{> home.mu}}
</html>

Which works fine. But now I want to convert it so that I can pass the name of the template to include as a string in the view that is rendered. Like this:

var stream = mu.compileAndRender('page.mu', {
    content: "home.mu"
});

And the modified page.mu template:

<html>
    {{> content}}
</html>

But it does not work. Mu chucks an error at

DEBUG: TypeError: Cannot call method 'replace' of undefined
at Object.Parser (/Users/sensis/projects/Happiness Index/server/node_modules/mu2/lib/mu/parser.js:15:28)
at Object.parse (/Users/sensis/projects/Happiness Index/server/node_modules/mu2/lib/mu/parser.js:10:16)
at /Users/sensis/projects/Happiness Index/server/node_modules/mu2/lib/mu.js:37:21

I've also tried rendering home.mu separately, but I've not been able to figure out how to convert a stream to a string for inclusion in the view for rendering page.mu.

I suspect that I need to redesign this to all work asynchronously, but as I'm new to node.js, I've not been able to figure out how to do this.

Any ideas how to approach this?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.