Using Slim or Haml & Sass / SCSS with Node.js? - javascript

I have a rather robust project that has all of its templates implemented in Slim and a little Haml. I'm considering moving the project over to a Node.js based structure (probably built atop Tower.js or something similar; maybe Meteor), however I would like to continue using Slim or Haml for the templates rather than shifting over to another template engine.
Has anyone done this or spent the time to figure out how to accomplish this so far, and if so, what were your findings?

Tower.js wraps the express.js template engine system, so you should be able to use any express.js template engine by adding the following to the configuration Tower.View.engine = "haml"
Tower.js uses mint, which has HAML built in, so you just need the haml module in your directory.
Slim is problematic though. First its not within mint.js directly, so you'll need to register a new template engine. Todo that you'll need to
create a function customAdapter that mint.js can use, you can look at the mint.js sourcecode. Heres an example of the haml adapter function:
function(content, options, callback) {
var result;
result = require('hamljs').render(content, options || {});
if (callback) {
callback.call(this, null, result);
}
return result;
}
you'll need to add the adapter to mint.js by doing require("mint").engines.slim = customAdapter
But there's no express.js engine for Slim, and since Slim contains ruby code snippets, it isn't likely there will be.
If you really want to do it so you'll need to create your own javascript parser for the template files (probably using something like http://opalrb.org/ , though with no specific ruby libraries), and then create an express.js engine (which I don't know how to).
I doubt it will be a very fruitful exercise.
I suggest you either convert your Slim files to haml (or jade, or any template engine that can be used by express.js) or don't make the move.
I could also not find any way to automatically convert Slim to haml or any other template engine (probably due to the fact that it contains ruby code), so you will have to do the conversion entirely manually.

Related

compiling node.js code to non-node-needed code

I am using ASP.NET MVC to build a web application, and I have fallen in love with the library Q.js, available here:
Q.js
Right now, I am using version 1.0, I load it up in the way that is most natural to me as an ASP.NET MVC developer. I have a place in my BundleConfig that just loads the script with my other scripts.
BundleConfig.cs
public static class BundleConfig {
public static void RegisterBundles(BundleCollection bundles){
bundles.Add(new ScriptBundle("~/bundles/scripts")
.Include("~/content/scripts/jquery.js")
// lots of other includes
.Include("~/content/scripts/q.js"));
}
}
So then in my view _Layout.cshtml, it's the normal simple process...
_Layout.cshtml
<head>
#Scripts.Render("~/bundles/scripts")
</head>
Easy enough, right? Yes, it works fine. But I notice that Q.js has another branch labelled v2.
Now, from what I can immediately tell, they are not that much different, but I do not believe the creator would have made a version 2 if they were not doing it to improve the product. I'd like to try it out, but this is where my experience fails me.
version 2 seems fundamentally different than version 1. Here is a link to it for quicker reference; Qv2
The q.js file starts out with this at line 43.
require("collections/shim");
var WeakMap = require("collections/weak-map");
var Iterator = require("collections/iterator");
var asap = require("asap");
I am accustomed to the require function being a part of requirejs, but I don't believe that is the purpose being served here. I in fact think this is intended to be consumed/run/used by node.js.
Now, since I am using ASP.NET MVC, I won't be using node.js. I've attempted to just put the expected folders and files in the right place so that they would be path relative to q.js, but that does not seem to satisfy it.
The Actual Question
Is there a way I can 'compile' Q.js 2.0 into a .js file that will not require node.js, and can be loaded normally within my ASP.NET MVC project? Can I use node.js to actually create an output .js file that has everything I need?
browserify is a tool for Node that takes all of the require()d dependencies, resolves them, and packages them into a single JavaScript file servable to the browser.

confusion between Jade and Handlebar

Trying out backbone+express with Jade as default templating.
Following a tutorial here(Great tutorial)
Confusion:
Many tutorials about backbone uses underscore template or handlebar to compile and render view.
I was using Jade as default template engine. My question is if I am using Jade then do I have to use another templating like Handlebar or underscore. If not how can I achieve following in Jade
render: function() {
var template = $("#booktemplate").html();
var compiled = Handlebars.compile(template);
var html = compiled(this.model.attributes);
this.$el.html(html);
return this;
},
My assumption: I am thinking Jade and Handle bar both are templating system and can be used alternatively. Is it so?
Why not use both Jade & Handlebar? I dont want to use two different syntaxes
#{} from jade / {{}} from Handlebar
Using Jade on the browser is not really a simple task. Thing is Jade is built for server side and does not support browsers.
This is why you'll often see people using two templates engines (if they use Jade). Some others are just gonna use Handlebars or Underscore everywhere - this is easier because templates engine working in the browser should work on the server. The other way around is not always true though.
Point to be taken here is that before starting to use a template engine, make sure it supports the environment you wish to target. There's plenty of options in term of engine, and this site can help you find one fittings your need: http://garann.github.io/template-chooser/
If you're really like Jade, then, you can use a stack like Browserify and some middleware (Jadeify) to make it work after pre-compilation. But you need to buy into the browserify concept and accept to precompile everything, everytime. You can check this related question for more details: https://stackoverflow.com/a/6623561/1024223

Backbone: managing templates

I'm using underscore template engine for an backbone application. As of now I have over 15 templates in the <head>. Its getting hard to maintain. So far, most of the solutions I seen to manage templates ended up needing them to be js files. That's also a headache, I prefer them to be html files for editing purposes.
I took a look at requirejs and not sure if I need that since it kinda revolves around a more modular approach that I can't say I'm using at the moment (although I will soon).
What will be the best way to manage templates and load/cache them as needed?
Personally we needed a robust solution at my company, so we went with:
Require.js - for module loading
Handlebars - for more powerful templating than Underscore can offer
HBS - an excellent require plug-in from Alex Sexton that handles bringing compiled templates in via Require
With this setup I can keep all of my templates in their own file, and then to use them I have files like this:
define(['template!path/to/someTemplate'], function(someTemplate) {
var MyNewView = BaseView.extend({template: someTemplate});
$('body').append(new MyNewView().render().el);
}
(and as you might guess we have a base Backbone view called BaseView which uses the view's template property to render the view).
Now, all that being said, if you don't need such a robust setup then Require may not be for you. In that case I would do the following:
Put all of your templates in to one or more HTML files; wrap them in script tags, like so:
<script id="dummyTemplate" type='text/template'>
<span>I'm a template!</span>
</script>
Write some code on your server-side to include those HTML files in the main HTML file you send to the client
Write a function which takes a template ID, gets the text of that element, compiles it in to a template, and returns that template (maybe cache the compiled templates if you want ... of course, with Underscore templates I don't think you even need compiling, so you can skip all that).
Use your function to access your templates: $("#something").html(templateFunc('dummyTemplate').template())
This will allow you to store your templates in html files (for syntax coloring), but still access them conveniently in JS. You can also divide your templates between as many files as you want, as long as you can write include logic to bring them in.
If you do opt for Require though, definitely check out the HBS plugin. And if you haven't looked at Handlebars templates yet, you might want to; they're far more powerful than Underscore ones (but like any good templating system, don't allow for too much logic).
Not sure what you mean by it being unmaintainable. Is it just a long list?
You don't need to keep your templates in the head. They can be at the bottom of your body as well. They just need to be defined before you try to use them.
One thing you might look into, depending on the server technology you are using would be to separate your templates into a different HTML file and include it at runtime.

JavaScript templating

I was trying to convince a fellow co-worker into using Mustache/Hogan in the front-end of a project and I proposed the following:
Having a templates.js file, which could roughly look like this:
var tpl_alert = '<div class="alert">{{msg}}</div>';
var tpl_welcome = '<p class="user-{{type}}">Welcome, {{name}}</p>';
...
Then, we would include templates.js and use the corresponding tpl in the Mustache/Hogan.js rendering.
My proposal was turned down, since we're hardcoding html templates into js variables.
Is this really that bad? Which are other alternatives to this?
To answer your question, putting your templates in javascript variables inside a static JavaScript file makes it difficult to maintain your templates. You need to worry about string escaping whenever you want to make a simple change. And 1 syntax error will crash your app.
However, putting all your templates in a single JavaScript file is the fastest way to load your templates.
Your alternatives are:
Storing your templates in seperate files and generating the static template.js file as a prebuild step.
Loading your html template files async through AJAX into javascript variables.
Using a library like Require.js that will load your templates asynchronously as needed into variables.
My preferred way of doing this is to create a separate template file that can be loaded dynamically in development and baked into pure js for production.
Specifically I use eco templates (I wouldn't recommend them unless you're familiar with coffee script) and Stitch for node.js. Stitch supports custom engines tied to file extensions, so when it finds an eco file in my project directory it compiles it into a Javascript function. I can now include that function in any other part of my application using the stitch provided require function using the original path of the eco file. So if the template resided in src/views/listItem.eco I would run var listItemView = require('views/listItem'); to fetch it and use it like this
var html = listItemView({item: items[i]});
$someElement.html(html);
You could use require.js instead of stitch if course, or any other similar framework.

How to integrate CouchApp, Node.JS, Sammy and Mustache

I set up a node.couchapp.js CouchApp and pushed it to my CouchDB. There is Sammy and jQuery included by default. Now, I'd like to add Mustache for templates, but don't exactly know where? I could use it as Node.js module or jQuery plugin.
I started with some sample code, just to see if it works, but it doesn't:
ddoc.lists = {
"basic": "function (head, req) { var that = this; provides('html', function () { var to_html = require('modules/mustache').to_html; var members = []; var row; while (row = getRow()) { members.push({club: row.key[0], name: row.key[1]}); } return to_html(that.templates['roster.mustache'], { members: members }); }) }"
};
Results in:
{"error":"invalid_require_path","reason":"Object has no property \"modules\". ...
Project structure is:
. Project
| - app.js
| - attachments
| - - scripts
| ` - index.html
| - modules
| | mustache
| - ` - mustache.js
` - templates
Update
I modified the code a bit and excluded the template folder as possible cause. This snippet is from a solved question here on SO, so it should actually work. But it's still the same error. I installed mustache.js with npm install mustache and renamed the folder from node_modules to modules (didn't work with node_modules either).
"basic": "function (head, req) { provides('html', function () { var template = '{{%IMPLICIT-ITERATOR}}{{name}}: <ul> {{#items}}<li>{{.}}</li>{{/items}} </ul>'; var mustache = require('./modules/mustache/mustache.js'); return mustache.to_html(template,view);});}"
But it's still the same error.
I'm not sure about the specific error you're getting, but to your question:
"Now, I'd like to add Mustache for templates, but don't exactly know where? I could use it as Node.js module or jQuery plugin."
You can use it in both.
As Node.js runs on the server-side this effectively gives you a way to define your template once (using Mustache in this case) and run it both server-side (using Node.js) and client-side (using the jquery-plugin).
Just for the overview (you may well already know this):
Imagine rendering a search-result of products:
The traditional way is to render the products with some server-side templating engine.
Now, let's say you want to enable filtering / sorting of the search-results. Generally speaking you have 3 options:
do a normal (non-ajax call) to the server, do server-side templating and spit out the new page
do an ajax-call to the server, do server-side templating and spit out html, pick it up client-side and insert it into a dom-element.
do an ajax-call to the server, generate a json-object, which you render client-side using a client-side templating engine (such as Mustache) into a dom-element.
Option 3 is arguably the best solution from a usability standpoint. (quick, low-bandwidth, no page flickering or page jumping, etc. ) . However think about a fallback/non-js way for SEO if you need it.
When implementing option 3 however you now have the situation of needing a server-side templating language to render products on the initial page load, and a client-side templating language to render products returned from subsequent ajax-calls. Both result in the exact same html. Not very DRY.
Here node.js comes into play, which eliminates the need for writing a seperate server-side template. Instead, just let node.js spit out the initial page using the exact same mustache template you use on the client-side.
Of course you could go the only client-side route: spitting out json on the intial page load as well, and render that on the client. This of course if terrible from a seo-standpoint. Some apps don't the search engine indexing however, in which case the 'everything on the client' approach is a good alternative.
Some related questions:
Client-side templating language with java compiler as well (DRY templating)
Good DRY approach to rendering and AJAX updating of page

Categories