Coder Social home page Coder Social logo

dustjs's Introduction

Dust

Asynchronous templates for the browser and node.js

Why?

I like Mustache and variants but none of them offers quite what I need.

Use Dust if you want these things:

  • async/streaming operation
  • browser/node compatibility
  • extended Mustache/ctemplate syntax
  • clean, low-level API
  • high performance
  • composable templates

Composable templates?

{^xhr}
  {>base_template/}
{:else}
  {+main/}
{/xhr}
{<title}
  Child Title
{/title}
{<main}
  Child Content
{/main}

Installation

In Node:

$ npm install dust

To render compiled templates in the browser:

<script src="dust-core-0.3.0.min.js"></script>

Demo & Guide

Extensive docs and a full demo are available at http://akdubya.github.com/dustjs

dustjs's People

Contributors

stonecobra 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

dustjs's Issues

Testing `foo instanceof Context` is fugly

I've been using foo instanceof dust.makeBase({}).constructor: that seems clunky. I'd like a way to get the constructor directly, without having to instantiate an object: foo instanceof dust.Context.

Eliminating makeBase() altogether might also belong on the table here? Swapping the stack and global arguments would make Context operate very much like makeBase does now. Further, no external code at present relies on Context() directly; the only change required would be adding a couple null or undefined leading parameters in dust.js proper.

can't use block name with minus symbol

When I tried the following template
{+my-title}
Base Title
{/my-title}

I got the error:
SyntaxError: Expected buffer, comment, partial, reference, section or special but "{" found.

context, partials and blocks

I wasn't sure where to ask this since there doesn't seem to be a mailing list for this project so I'll ask it here.

I was wondering the following:

  1. is there a way to add to the context from inside a template.
  2. Can you add to the context in one template/partial and pass that update to another template via the partials/blocks mechanism?

Here's code for my current attempt:

The code for the helpers/sections that I pass to the context before calling render:

{

    'css': function(chunk, context) {
        var template='<link rel="stylesheet" type="text/css" href="/media/css/{file}.css" />'
        var css = context.get('css');
        Array.from(css).each(function(file){
            chunk.write(template.replace('{file}',file)).write('\n');
        });
        return chunk;
    },

    'cssAddFile': function(chunk, context, bodies, params) {
        //check if css key defined
        var head = context.current();
        if (nil(head.css)) {
            head.css = [];
        } else if (typeOf(head.css) != 'array') {
            head.css = Array.from(head.css); //mootools function, take it out if you have an issue with it.
        }
        head.css.push(params.file);
        return chunk;
    }

}

and then I have the following "base" template:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
    <title></title>
    {#css/}
</head>
<body>
    <div id="banner">&nbsp;</div>
    <div id="page">
        <div id="content">
            {+content/}
        </div><!-- content> -->
    <div id="footer"></div><!-- footer -->
    </div><!-- page -->
</body>
</html>

which I then try to call using this:

{#cssAddFile file="index_styles"/}

{<content}
    <p>This is the content of the page.</p>
{/content}

{>"base"/}

I expect the output to have a element with the index_style.css file reference but it never comes through.

Am I doing this right or is there another way to do this?

Thanks,
Jon

Helpers don't support . syntax

When I push a native object onto the stack, I can navigate with dot syntax, for example:
{user.FirstName}
If I make user a helper function, like this in dust.makeBase:
user: function(chunk, context){
var req = context.get('req');
return req.session.user;
}
and then try the same, it doesn't work:
{user.FirstName}
but this does work:
{#user}{FirstName}{/user}

Am I doing something wrong?

require.paths not supported for Node.js 0.6.13

Hi all,

I try to run dust.js in a node.js script.
I meet the following issue (see stack trace bellow)

It seems the "require.path" statment is no more supported. And you use it in your file server.js

node.js:201
        throw e; // process.nextTick error, or 'error' event on first tick
              ^
Error: require.paths is removed. Use node_modules folders, or the NODE_PATH envi
ronment variable instead.
    at Function.<anonymous> (module.js:378:11)
    at Object.<anonymous> (C:\workspace\node.js\my_project\tools\node_modules\dust\
lib\server.js:6:8)
    at Module._compile (module.js:441:26)
    at Object..js (module.js:459:10)
    at Module.load (module.js:348:31)
    at Function._load (module.js:308:12)
    at Module.require (module.js:354:17)
    at require (module.js:370:17)
    at Object.<anonymous> (C:\workspace\node.js\my_project\tools\node_modules\dust\
lib\dust.js:511:7)
    at Module._compile (module.js:441:26)

Thank you.

force_current example is not working

force_current example is not working

  1. {#person}{.root}: {name}, {age}{/person}
  2. {
    "root": "Subject",
    "person": {
    "name": "Larry",
    "age": 45
    }
    }
  3. : Larry, 45

The correct (4) result must be: Subject: Larry, 45

Regards: Evgeni

Iterate over properties of an object? Get name of properties?

Hello,

Looking for a way to iterate over an object structured like so:

{
  freenode : 'irc.freenode.net',
  oftc : 'irc.oftc.net',
  ipt : 'irc.ipt.net'
}

I need to output the key names and their values. After combing the docs for quite awhile, I dont see any information on how to do this.

Thanks,

Ralph

javascript single line comments cause parse error

Parser pukes on this:

  <script language="javascript">
    $(function(){
      $('#krutmnu a').click(function(e){
        //$('#body').children().hide().filter('#'+$(this).attr('href').replace(/#/,'')+'_panel').toggle(true);
      });
    });
  </script>

But not this:

  <script language="javascript">
    $(function(){
      $('#krutmnu a').click(function(e){
        /* $('#body').children().hide().filter('#'+$(this).attr('href').replace(/#/,'')+'_panel').toggle(true); */
      });
    });
  </script>

It looks like development here has stalled, but of course the great thing with open source is I can fix this myself but I think I'll wait and see if this is covered in the linkedin fork which is supposed to show up soon http://engineering.linkedin.com/frontend/client-side-templating-throwdown-mustache-handlebars-dustjs-and-more

Unable to get line number out of SyntaxError

I am trying to emit a user-friendly error message when a template fails to pass dust parser. At first glance, this should be easy, as dust parser.js source looks like it passes the error line and column to SyntaxError constructor. However, that does not happen.

It appears that despite defining result.SyntaxError, dust creates a plain jane native SyntaxError that has no knowledge of line or column. result.SyntaxError constructor seems to be never called at all. Renaming result variable on left side of var result = parse_body() (to unshadow outer result) and replacing new SyntaxError call with new result.SyntaxError allowed line numbers to be passed properly.

Am I doing something wrong here or misunderstanding the way exception reporting should work? My environment is node 0.4.3 on OS X.

Unflushed Chunks

Sometimes dust gets stuck in an asynchronous block at the end of a template. We have our own subtemplate/partial include system, and sometimes, for some templates, after ending a stub, it doesn't get flushed.

I fixed the issue locally like this, but it's kinda scary: (works for our use cases though)

Stub.prototype.flush = function() {
  var chunk = this.head;

  while (chunk) {
    if (chunk.flushable) {
      this.out += chunk.data;
    } else if (chunk.error) {
      this.callback(chunk.error);
      this.flush = function() {};
      return;
    } else {
      // Sometimes, dust get's stuck here, at the end of a template, and something thinks there's more to do
      // chunk.next is undefined
      if (!chunk.next && "" === chunk.data) {
        break;
      }
      return;
    }
    chunk = chunk.next;
    this.head = chunk;
  }
  this.callback(null, this.out);
}

Also, for reference, here's our custom include helper:

dust.helpers.include = function (chunk, context, bodies, params) {
  return chunk.map(function(chunk) {
    var ctx = (params && params.context) || context.get("context") || context.current();
    ctx.currentDustIndex = context.stack.index;
    ctx.currentDustLength = context.stack.of;
    Gilt.Template.render((params && params.name) || context.get("name"), ctx, function (html) {
      chunk.end(html);
    }, {
      engine:  (params && params.engine)  || context.get("engine") || "dust",
      version: (params && params.version) || context.get("version")
    });
  });
};

And an example of it in use:
{@include name=\"cart\" version=\"countdown\" context=sku/}

Documentation mentions dust.Context.base but Context is no longer exposed

The documentation mentions creating a base Context a couple times:

// Set up a base context with global helpers
var base = dust.Context.base({
sayHello: function() { return "Hello!" }
});

But the code to expose the Context was removed a few days ago according to the history so this code does not work. Should the documentation be changed? Or should the ability to create a base Context be exposed with some other method?

Nested templates don't support multi-level block overrides

I'd like to have a 'base' layout, section specific layouts that extend the base layout, then pages extending the section specific layouts. However I can't get blocks in the page templates to show up if they're defined in the section template. Here's a simple example:

base.dust
(html)
(head)
(title){+title}Home{/title} : MySite(/title)
{+head/}
(/head)
(body){+body/}(/body)
(/html)

section1.dust
{>base/}
{<head}
(script src="...")(/script)
{/head}

page1.dust
{>section1/}
{<title}Page 1{/title}
{<head}
(link rel=stylesheet href="...")
{/head}
{<body}
PAGE BODY
{/body}

The desired result would be a page with both the 'script' tag and the stylesheet 'link' tag in the head. How do I do that, without having to define new blocks in each template? (which would be problematic if the number of nested templates varied from page to page)

Here's a fiddle where I've been playing with this, for reference:
http://jsfiddle.net/laurie/dxDyN/1/

Nested templates don't support multi-level block overrides

I'd like to have a 'base' layout, section specific layouts that extend the base layout, then pages extending the section specific layouts. However I can't get blocks in the page templates to show up if they're defined in the section template. Here's a simple example:

[base.dust]


<title>{+title}Home{/title} : MySite</title>
{+head/}

{+body/}

[section1.dust]
{>base/}
{<head}
<script src="..."></script>
{/head}

[page1.dust]
{>section1/}
{<title}Page 1{/title}
{<head}

{/head}
{<body}
PAGE BODY
{/body}

The desired result would be a page with both the 'script' tag and the stylesheet 'link' tag in the head. How do I do that, without having to define new blocks in each template? (which would be problematic if the number of nested templates varied from page to page)

Here's a fiddle where I've been playing with this, for reference:
http://jsfiddle.net/laurie/dxDyN/1/

Feature: Add AMD support

Would love an AMD version of dust that works with RequireJS that kicked out AMD compiled templates as well.

Partials with block content

The peg grammar treats partials differently from other sections, requiring the 'partial' tag to be self-closing, so it isn't valid to do

{>partial}...stuff...{/partial}

Could support for this be added, along with blocks, so you could write, for example:

{>partial}
    {<heading}Title{/heading}
    {<content}
        ...markup...
    {/content}
{/partial}

The heading/content sections would remain on the context stack for the duration of partial, then be popped.

This would be a more natural syntax when using inline partials for layout but, more importantly, it would allow partials to be reused within a page for rendering repeating elements with varying content. I'd use this, for example, to standardize how forms are marked up across an app/site whilst keeping the actual form elements local to the calling template.

different instances of dust

I use dust in my framework which can be used by few aplications at the same time. Each application uses unique dust.cache and that makes conflicts, cause I index views in cache by relative paths to them. I want dust can to make several instances of itself.

ps: sory for my english

Access nth element of an array

I couldn't find a mailing list, so here goes:

I'm trying to access only the first element of an array in my template:

{#people.0}
  Hello, {name}
{/people.0}

However, that gives me a syntax error. Is it possible to access only the first element, or do I need to write a function for this?

Thanks for a great lib!

create google group

I believe it makes sense to create Google Group for this project.
With this email based group people who are using your project will be able to ask questions and discuss some ideas/issues.
Without creating the group market of DustJS always will be very limited. And this is unfortunately.
I have a perfect example how the Google group can effectively improve usability of the project and help users to use it in full scale. See the link below:
http://groups.google.com/group/rgraph/topics

Global alias or how to pull a block

I'm trying to write a
base template with blocks witch after in a
child template to reuse only some blocks from the base template and I followed global alias help for dust
but when I use them with partial doesn't want to work.

greeting.dust

{<greeting}Hello, Hola{/greeting}   
{<world} Us, Spain{/world}

partial_end.dust

{#names}
  {.} {+greeting/}
{/names}

{#projects}
  {.} {+greeting/}
{/projects}
{>greeting_template/}

partial_begining.dust

{>greeting_template/}
{#names}
  {.} {+greeting/}
{/names}

{#projects}
  {.} {+greeting/}
{/projects}

In only one file it works like this:

greeting_begining.dust

{<greeting}Hello, Hola{/greeting}   
{<world} Us, Spain{/world}
{#names}
  {.} {+greeting/}
{/names}

{#projects}
  {.} {+greeting/}
{/projects}

but I need to separate the blocks in other files.
Can some one help? I there any other way of doing this?
If now there is an real issue with this maybe I can contribute to dust and try to fix this.

PS: from the main examples it seem that blocks are global when included from partials, but this is the other way around.

"yield" or "body" method?

A common use case is to have a layout like so

layout.dust

<h1>header</h1>
{=body}
<p>Footer</p>

And then have a template use that layout

home.dust

{>layout}
<p>I am the content</p>

Which would render:

<h1>header</h1>
<p>I am the content</p>
<p>Footer</p>

Right now I'm doing it like this:

layout.dust

<h1>header</h1>
{+body}{/body}
<p>Footer</p>

home.dust

{>layout/}
{<body}
<p>I am the content</p>
{/body}

Is the first way supported? If not, consider this a feature request :)

Dust is not working in node v0.6

Hi,

Just wanted to let you know that Dust is not working in the latest version of node. It throws the following exception

Error: require.paths is removed. Use node_modules folders, or the NODE_PATH environment variable instead.
at Function. (module.js:376:11)
at Object. (/Users/satheesh/NodeTraining/Express/node_modules/dust/lib/server.js:6:8)
at Module._compile (module.js:432:26)
at Object..js (module.js:450:10)
at Module.load (module.js:351:31)
at Function._load (module.js:310:12)
at Module.require (module.js:357:17)
at require (module.js:368:17)
at Object. (/Users/satheesh/NodeTraining/Express/node_modules/dust/lib/dust.js:511:7)
at Module._compile (module.js:432:26)

Thanks!

exists/notexists sections don't work for inline partial blocks

Sometime a block should be wrapped by other markup, but that markup should only be included when the block is defined:

base.dust*

{?block}
<div class="my-block">
    {+block/}
</div>
{/block}

template.dust

{>"base.dust"/}
{<block}wrap this with a classed div{/block}

The {?block} check never succeeds, so neither the block nor the wrapper markup get output to the result stream.

img tags with dust variable in src attribute does not work in firefox browser

<title></title> <script type="text/javascript" src="dust-full-0.3.0.js"></script> <script type="text/javascript"> function justDoIt() { var resp = { "name": "Mick", "count": 30, "thumbnail" : "http://localhost:8080/b2b2/i/DEFAULT_PLACEHOLDER_SMALL.jpg", "asdf" : "sadf" };
            var x = document.getElementById("t_progList").innerHTML;
            alert('asdf' + x);
            var compiled = dust.compile(x, "t_progList");
            dust.loadSource(compiled);

            dust.render("t_progList", resp, function(err, out) {
                alert('data is = ' + out);
                document.getElementById("progList").innerHTML = out;

            });
        }
    </script>
Here
<div id = "t_progList" style="display:none">
    Hello {name}! You have {count} new messages.
    <pre>
    <img src = '{thumbnail}'>
    </pre>
</div>

partials issue

hi, i have to tried to use the partial {>'/templates/noticias.dust.html'/} inside a template but i get this error:

Error: Expected buffer, comment, partial, reference, section or special but "{" found.
Archivo de origen: 1
Línea: 1

thanks for the help!!!

Abandonware?

Haven't seen any updates to the project for a long time, is this effectively abandoned?

Global objects not path-able

Pathing only works for objects that are in a context, not the global space. I've been using this kludge-tastic helper as a workaround to resolve paths out of the global namespace. I'd like to not have to use it.

function _global(chunk,ctx,bodies,params){
    var cur= ctx.get(params.root),
      i= 0
    while(true){
        var param= params["p"+(i++)]
        if(param === undefined)
            break
        cur= cur[param]||cur.get&&cur.get(param)
    }
    chunk.write(cur)
}

It's used like this: {#global root="foo" p0="bar" p1="baz"/}

From: makeBase({foo:{bar:{baz:77}}})

Why filters doesn't work for empty values?

I want always show some variable as boolean, even it's undefined. I wrote filter:

dust.filters.b = function( value ){
  return value ? 'true' : 'false';
}

and used it:

{some_variable|b}

but undefined and false shown as empty string.

Helper params are not processed correctly

In the documentation, one may read :

Parameters accept interpolated string literals as values: {#snippet id="{name}_id"/}

However, here is a test case that shows that it currently does not work :

Template

Test: {#helper foo="{name}_2"/}

Context

{
"name": "tester",
"helper": function(chunk, context, bodies, params) {
return chunk.write(params.foo);
}
}

Expected Output

Test: tester_2

Effective Output

Test: function body_1(chk,ctx){return chk.reference(ctx.get("name"),ctx,"h").write("_2");}

Maintaining whitespace on per-section basis

Dust documentation describes a way to enable or disable automatic whitespace removal during compilation. However, it does not seem to show a way to selectively preserve whitespace in certain sections of template while allowing removal to run its course elsewhere. The practical use case is to let whitespace be removed from HTML while preventing concatenation of lines in inline JS (as JS whitespace removal will require abandoning // comments and require more attention to semicolons). How would you suggest approaching this?

I am thinking of defining a custom pragma that will set a flag on compiler object, and changing optimizers.format to switch between noop and nullify based on that flag. Is that a sane approach, or is there something simpler I should try?

compileAndRender and compileToFunction

It would be nice if we didn't have to compile templates to a name, and could just say

dust.compileAndRender(fs.readFileSync(...), { ... }, function(rendered) { ... });

Or if we could compile the template to a function that just takes data.

var func = dust.compileToFunction(fs.readFileSync(...));
func({...}, ...);
func({...}, ...);
func({...}, ...);
// and so on

I don't have a need for the named templates stuff, but still think dust is really cool. I do a lot of templating with one off templates that aren't going to be used again, and having a more flexible way of using Dust would be awesome!

Parser syntax errors should be passed to the callback, not thrown

When the parser encounters a syntax error, it currently throws a SyntaxError exception instead of bubbling it up to the render callback like I'd expect. Catching this exception is proving to be a challenge in an Express app. I'd much rather be able to handle it in my callback.

Empty context array does not execute {:else} block

I'm not sure if this is more a feature than a bug. Please enlighten me.

The template _{#foo}x{:else}y{/foo}_ with context {"foo":[]} renders to __. Shouldn't this be _y_? Is there any other way to check if an array is empty and print a note about that?

require.paths is removed

When I try to include dust using dust = require('dust'), I get the following messageL

Error: require.paths is removed. Use node_modules folders, or the NODE_PATH environment variable instead.

How can I solve this error?

I am using version 0.6.7 of Node and the platform is Windows.

Asynchronous context data

I might be missing something, but is there a way to asynchronously add data to the context?

For your "{#list:projects}" example -- if the projects object was returned from an asynchronous function -- is that workable somehow?

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.