Giter VIP home page Giter VIP logo

jaml's Introduction

Jaml: beautiful HTML generation for JavaScript

Jaml tries to emulate Ruby’s Haml library, making it easy to generate HTML in your JavaScript projects.

Examples

Something Simple

Registering a template is easy:

Jaml.register('simple', function() {
  div(
    h1("Some title"),
    p("Some exciting paragraph text"),
    br(),

    ul(
      li("First item"),
      li("Second item"),
      li("Third item")
    )
  );
});

So is rendering it:

Jaml.render('simple');

Here’s the output (yes, the indentation really is that pretty):

<div>
  <h1>Some title</h1>
  <p>Some exciting paragraph text</p>
  <br />
  <ul>
    <li>First item</li>
    <li>Second item</li>
    <li>Third item</li>
  </ul>
</div>

Templating

Usually we want to inject data into templates – let’s see how to do that:

Jaml.register('product', function(product) {
  div({cls: 'product'},
    h1(product.title),

    p(product.description),

    img({src: product.thumbUrl}),
    a({href: product.imageUrl}, 'View larger image'),

    form(
      label({for: 'quantity'}, "Quantity"),
      input({type: 'text', name: 'quantity', id: 'quantity', value: 1}),

      input({type: 'submit', value: 'Add to Cart'})
    )
  );
});

And now to render it:

//this is the product we will be rendering
var bsg = {
  title      : 'Battlestar Galactica DVDs',
  thumbUrl   : 'thumbnail.png',
  imageUrl   : 'image.png',
  description: 'Best. Show. Evar.'
};

Jaml.render('product', bsg);

Which gives us:

<div class="product">
  <h1>Battlestar Galactica DVDs</h1>
  <p>Best. Show. Evar.</p>
  <img src="thumbnail.png" />
  <a href="image.png">View larger image</a>
  <form>
    <label for="quantity">Quantity</label>
    <input type="text" name="quantity" id="quantity" value="1"></input>
    <input type="submit" value="Add to Cart"></input>
  </form>
</div>

Collections and partials

We can reuse templates inside other templates. Here we make a Category template to hold more than one product:

Jaml.register('category', function(category) {
  div({cls: 'category'},
    h1(category.name),
    p(category.products.length + " products in this category:"),

    div({cls: 'products'},
      Jaml.render('product', category.products)
    )
  );
});

Now we render it with a couple of products:

//here's a second product
var snowWhite = {
  title      : 'Snow White',
  description: 'not so great actually',
  thumbUrl   : 'thumbnail.png',
  imageUrl   : 'image.png'
};

//and a category
var category = {
  name    : 'Doovde',
  products: [bsg, snowWhite]
}

Jaml.render('category', category);

Which gives us:

<div class="category">
  <h1>Doovde</h1>
  <p>2 products in this category:</p>
  <div class="products"><div class="product">
  <h1>Battlestar Galactica DVDs</h1>
  <p>Best. Show. Evar.</p>
  <img src="thumbnail.png" />
  <a href="image.png">View larger image</a>
  <form>
    <label for="quantity">Quantity</label>
    <input type="text" name="quantity" id="quantity" value="1"></input>
    <input type="submit" value="Add to Cart"></input>
  </form>
</div>
<div class="product">
  <h1>Snow White</h1>
  <p>not so great actually</p>
  <img src="thumbnail.png" />
  <a href="image.png">View larger image</a>
  <form>
    <label for="quantity">Quantity</label>
    <input type="text" name="quantity" id="quantity" value="1"></input>
    <input type="submit" value="Add to Cart"></input>
  </form>
</div>
</div>
</div>

Error handling

If the requested template does not exist, the renderer will return null:

=> Jaml.render('missing');
=> null

Jaml Tests

You can run the Jaml test suite using either node.js at the command line or via a webpage-based runner.

Run the tests in a browser

Jasmine must be checked out in a directory alongside jaml:

git clone https://github.com/pivotal/jasmine.git
ls
=> jaml jasmine

…then open specs/index.html in your browser.

Run the tests using node.js

1) Install node.js.

2) Check out sconover’s jasmine-node alongside jaml:

git clone https://github.com/sconover/jasmine-node.git
ls
=> jaml jasmine-node

3) Run the suite:

$ node specs/suite.js 
Started
..........................

Finished in 0.018 seconds
X tests, Y assertions, 0 failures


jaml's People

Contributors

d2kagw avatar edspencer avatar erikvold avatar kesla avatar paulmars avatar savetheclocktower avatar sconover 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

jaml's Issues

If and for in template

Does JAML support if and for statements in template? If it is already supported, please add it to README.

Error reporting could be infinitely improved

When a template fails to compile, it'd be ideal to know which template (and ideally where in that template) the error occurred. AFAICT at the moment you usually get no visibility at all other than knowing it's a Jaml error.

Access to index of array

I'd like to be able to access the index of an array that is rendered with a Jaml template. Is this possible and would you like to see it in the library?

I took a look but couldn't see where/how to add this. I'd be glad to work on a patch if you can give me some advice.

Thanks!

Indentation reset when nesting Template

I was please to see the indent feature, especially since it match my coding style (a 2 space indent ;-)

But, I notice, indentation got reset when nesting template.

Ex. The following JavaScript

var sys = require("sys");
var Jaml = require("jaml").Jaml;

/* --------------------------------------------------------------- */
Jaml.register('html', function(data) {
  html(
    head(
      title(
        'Jaml rocks'
      )
    ),
    body(
      Jaml.render('body-content', data)
    )
  );
});

/* --------------------------------------------------------------- */
Jaml.register('body-content', function(data) {
  h1(
    'Why Jaml rocks'
  ),
  ul(
    Jaml.render('reason', data.reasons)
  )
});

/* --------------------------------------------------------------- */
Jaml.register('reason', function(reason) {
  li(
    reason
  );
});

/* --------------------------------------------------------------- */
sys.puts(Jaml.render('html', {
  reasons: [
    'too cool to be true',
    'elegant syntax; easy to read, easy to use',
    'great combo with node.js'
    ]
}));

Ouput

<html>
  <head>
    <title>Jaml rocks</title>
  </head>
  <body><h1>Why Jaml rocks</h1>
<ul><li>too cool to be true</li>
<li>elegant syntax; easy to read, easy to use'</li>
<li>great combo with node.js</li>
</ul>
</body>
</html>

Instead of the hope result

<html>
  <head>
    <title>Jaml rocks</title>
  </head>
  <body>
    <h1>Why Jaml rocks</h1>
    <ul>
      <li>too cool to be true</li>
      <li>elegant syntax; easy to read, easy to use'</li>
      <li>great combo with node.js</li>
    </ul>
  </body>
</html>

Do you have any plan to support proper indention when nesting template ?

Thanks.

TFOOT tag is missing

TFOOT is a valid element within the TABLE element, but the definition is missing.

Use class instead of cls to be consistent

In my opinion, Jaml should use "class" instead of "cls" for setting the class attribute on a dom element to be consistent with the way other attributes are set. It seems that "cls" is the only one that has been "minified" instead of using the actual attribute name

No support for boolean attributes

It would seem to be completely impossible to specify a boolean attribute in a template:

Jaml.register('blah', function(checked){
  input({ type: 'checkbox', checked: checked });
}

Outputs:

<input type='checkbox' checked="false">

Which is clearly not what the developer wanted.

How to use this with Rails app?

Hi,
I'm pretty impressed with HAML like js rederer.
But I'm confused how to use this with Rails app??
Where to put what and how to render on the view as a callback to replace the rendered jaml?

Produces invalid HTML when div has no content

The code

div({ cls: 'rect1' });

produces

<div class="rect1"/>

which is not valid HTML!

What possessed you to keep a list of non-self-closing tags and have all others self-close, rather than specifying a (very small) list of tags that can self-close?

notSelfClosingTags: ['textarea', 'script', 'em', 'strong', 'option', 'select']
/* and by implication, everything else is self-closing!!!! */

This is clearly very silly.

Allow users to specify `this` for Templates

Atm if you have X which has an array of Ys and you do the following:

Jaml.register("x", function(X) {
    div(new Jaml.Template(function(Y) {
        // need parts of X here
    }).render(X.Ys))
})

You'll find that you cannot access parts of X where you need them, because templates are evald the closure is busted. The two options I can see here atm are to:

  1. Attach the data you need from X to some temp variable in the global, then access that while your in the sub Template.
  2. Attach the data you need from X, or just refs to X, to each Y which is a really bad option.

So I purpose option 3, using X as this for the sub Template, see here:

Jaml.register("x", function(X) {
    div(new Jaml.Template(function(Y) {
        var X = this; // this is X
    }).render(X, X.Ys))
})

It's not hard to keep this from breaking the old API (ie: when Jaml.Template.prototype.render is called with a single argument) because in that case the single argument would be both this and data. This also helps when looping through any array of elements if you wish to access other parts of the array.

No <strong> element?

Why not support the full set of HTML elements? Both the and elements are pretty common, widely accepted as kosher, and yet not included.

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.