How to use a handlebar template? - javascript

I bought a theme expecting it to have HTML and Angular versions but all I see are HBS files.
I am newbie to the grunt/express/npm the whole scenario and I'm lost on how to extract a possible html version from these files.
There is a Gruntfile.js and I tried running "grunt" on CLI but I get an error saying "unable to find local grunt file".
Feels like it is some sort of Handlebar template.
Below is the file structure.

Handlebar is nothing rather than a template engine on top of Mustache, which means it's possible to see HTML as well as interpolation variables inside. that.
As an example
Handlebars templates look like regular HTML, with embedded handlebars expressions.
<div class="entry">
<h1>{{title}}</h1>
<div class="body">
{{body}}
</div>
</div>
A handlebars expression is a {{, some contents, followed by a }}
You probably see more helpers such as {{#if}} or {{#each}} and etc, so make that easy to iterate or have other necessary logic in the template.
So, as you mentioned Angular, I assume angular is binding data with Handlebar as its template engine, Or alternatively, you may have Express app which uses Handlebar.
What you have to do is to extract HTML tags from handlebars template and just ignore {{...}} then replace your content appropriately with {{..}} instead.
It's possible to extract even with Grunt or other automation task runners like Gulp or Webpack. However, it may need more efforts and different plugins or specific code.
Remember, you need to also copy your CSS in order to see the same style for your HTML stylesheet.
Last but not least, There are other ways to extract or to get your template run, however, the simplest is to what I explained.
For more information read here
Regarding:
"unable to find local grunt file".
it's not as easy as one solution, there may be different problems. However, you will need to install (preferably) the latest grunt version:
npm install grunt --save-dev
that should work for yo as --save-dev will add grunt as a dev-dependency to your package.json. This makes it easy to reinstall dependencies.
Hope it works for you.

You can use this to convert those .hbs files to .js which you can include directly to your html I believe - https://github.com/yaymukund/grunt-ember-handlebars
grunt.initConfig({
ember_handlebars: {
all: {
src: 'src/templates/**/*.hbs',
dest: 'output/javascripts/templates.js'
}
}
});

Handlebars is semantic template engine which means your html is created as string. Handlebars is basically used to represent your data. for example,
JS
var context = {site : jsgyanblogspot.com };
Handlebars
<h3>{{site}}</h3>
At above, the part with h3 is handlebar, the expression {{site}} looks up the value in the current context and fetches the value jsgyanblogspot.com.
The handlebar part is converted to HTML through the compilation, In your case, you need to precompile the templates.
After precompiling, all template files would be converted to single js file(.hbs files => single.js).
Your single.js file contains the HTML. You need the respective npm modules for precompiling, just type npm install from your project directory agile, that installs the required npm modules.
If this still does not solve your problem, try to install grunt locally executing command sudo npm install grunt --save-dev from your project directory

Related

Is it possible to use ESLint to lint Handlebars template?

I'm trying to write an ESLint plugin for Ember to check if the handlebars template together with javascript code has no issues.
To achieve that, I need to lint .js component code together with .hbs component template.
I don't have much experience with writing ESLint rules, but I guess all I need is to somehow turn those .hbs files into AST and then lint it as usually, but I don't know how to do that.
Are those AST produced by Js and Handlebars even compatible?
I believe https://www.npmjs.com/package/eslint-plugin-html does what you're looking for:
A[n] ESLint plugin to lint and fix inline scripts contained in HTML
files.
By default, this plugin will only consider files ending with those extensions as HTML: .erb, .handlebars, .hbs, .htm, .html, .mustache, .nunjucks, .php, .tag, .twig, .we. You can set your own list of HTML extensions by using this setting.

How to use Node.js packages within a client-side html document using browserify

I'm unable to use a node.js module on my website with broweserify. The example only shows how to run a javascript file that is separate from the .html file, not how to use the node.js module within the .html file. Seems like a trivial problem, but I'm unable to make it work.
Here's what I've done:
Initialized node.js & installed a package, npm i webtorrent-health as an example
Created require_stuff.js which consists of a single line: var WebtorrentHealth = require('webtorrent-health')
Run browserify: browserify require_stuff.js > bundle.js
Include package in my html document, e.g. <script src='bundle.js'></script>
Use the package somewhere in my document, e.g. like this: <script>webtorrentHealth(magnet).then(foobazbar())</script>
Despite bundle.js executing and seemingly defining webtorrentHealth, the script within the .html document fails with WebtorrentHealth is not defined. What am I doing wrong? How do I make it work? Thank you!
You're very close to what you want to achieve. In fact, your code bundle.js is inaccessible from outside (in your case the browser) due to browserify, but you can expose your module by writing at the end of your file require_stuff.js:
window.WebtorrentHealth = WebtorrentHealth;
Now you can use WebtorrentHealth in your document.

How can I minify an ExtJs 5 project without Sencha?

I have been researching the ability to minify an ExtJS application without Sencha and the closest I have come to is this link:
Is there a way to minify an ExtJS application without Sencha CMD?
However, I am not sure how to execute the file in one of the later comments. I am using the minify-maven-plugin with com.samaxes.maven and the CLOSURE engine. I was able to generate the minified js file of the entire project but I get errors when I try to load the web page.
I was able to verify the web page was calling the correct file. I received the error "TypeError: q is undefined"...not helpful at all. Without the minified file, the web application runs perfectly. So, the generated minified file must have something wrong with it.
The suggestion at the bottom of the link above indicates the sequence of files that I should include but I have no idea how to actually implement this. Also, there are probably over a hundred javascript files that need to be minified so I would rather not have to type each file in the jsb file.
Are there any suggestions on how to minify my entire project at build time with maven?
I'm using Grunt to build the project, but it doesn't really matter as all you need is to combine files, so maven should be more than capable.
I wanted my dev version to still rely on Extjs dynamic class loader so I don't have to rebuild the project whenever I modify one file, and only production version to be minified into a single file. There were a few pitfalls before I got it working, here is what I ended up with. Also this is for ExtJS6, but it probably still should be the same.
It is all controlled by backend variable dev, which when set to false will use minified sources.
index.html (I'm using some meta templating language as example)
<html>
<head>
{{if dev}}
<script src="/ext/ext-all-debug.js"></script>
{{else}}
<script src="/ext/ext-all.js"></script>
{{/if}}
<script>
var dev = {{dev}};
Ext.Loader.setConfig({enabled: dev});
</script>
{{if dev}}
<script src="/app.min.js"></script>
{{else}}
<script src="/app.js"></script>
{{/if}}
</head>
<body></body>
<html>
app files, requires directive doesn't work well when the dynamic loader is disabled, so I had to add conditions like this everywhere:
Ext.define('MyApp.view.Panel', {
extend: 'MyApp.view.GenericPanel',
requires: dev ? [
'MyApp.view.AnotherView',
] : [],
...
});
Gruntfile.js (if you need only concatenation replace uglify with concat everywhere)
module.exports = function(grunt) {
grunt.initConfig({
pkg : grunt.file.readJSON('package.json'),
uglify : {
build: {
files: {
'../app.min.js': ['../app/view/GenericPanel.js', '../app/**/*.js', '../app.js'],
}
}
},
});
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.registerTask('default', [ 'uglify' ]);
};
grunt's project.json:
{
"name": "My App",
"version": "1.0.0",
"devDependencies": {
"grunt": "~0.4.5",
"grunt-contrib-concat": "^1.0.1",
"grunt-contrib-uglify": "^1.0.1"
}
}
The order of files matter, by default grunt will use alphabetic order. If you extend some class, the parent class has to be included higher. app.js should be at the end. Other than that it is working well in a single mixed file, so I didn't have to customize the file order further. Grunt has pretty powerful path patterns, so if you need to make sure some file is included first you just list it before other path patterns and it will be smart enough to not include it twice.
I recommend you start with simple concatenation without minification, and only if that works try minifying it. When minifying you might need to be careful with global functions and variables as they can be renamed if minifier is too aggressive. Grunt's minifier almost worked for me with the default settings, I just had to made couple small changes to my code (related to global functions).
While I am not sure why you would want this, the main thing you need is the so-called dependency tree - which tells you the order in which to include the source files.
Then you can put all the files (ExtJS source, libraries if applicable and also your own views) into one big file, in the correct order. This file should then work exactly as the 500 distinct files. (It did for me.)
That done, you can search for a working minifier. Not every minifier can minify ExtJS code, and I don't remember my last results before we finally decided to switch to Sencha Cmd, but I think Microsoft Javascript Minifier was one that worked for us.
Apart from that, minified JavaScript is really legible. You should provide the source of the error, with 200 characters before and 200 characters after the error, and I guess someone here can tell what's going on there.

How do I connect bower components with sails.js?

I'd like to be able to install Javascript dependencies through bower and use them in a sails.js app, but I can't figure out a way to do this with out just copying an pasting files from the bower_components folder to the Sails assets folder.
Ideally I think I'd like to use requirejs and point to the bower components in the main.js file. I may be trying to pound a square peg in a round hole, please let me know if so. Any thoughts on managing components/libraries with Sails are welcome.
In Sails 0.10 the 'assets/linker' directory no longer exists, however I found a lead on simple solution that gives some automation to the bower -> asset linker workflow while also allowing some granular control over what exactly ends up getting linked.
The solution is adding grunt-bower to your Sails.js compileAssets task
grunt.registerTask('compileAssets', [
'clean:dev',
'bower:dev',
'jst:dev',
'less:dev',
'copy:dev',
'coffee:dev'
]);
Then configure your grunt-bower task like so (as tasks/config/bower.js):
module.exports = function(grunt) {
grunt.config.set('bower', {
dev: {
dest: '.tmp/public',
js_dest: '.tmp/public/js',
css_dest: '.tmp/public/styles'
}
});
grunt.loadNpmTasks('grunt-bower');
};
This will automatically copy your bower js and css files to the proper place for Sail's asset linker to find and automatically add to your project's layout template. Any other js or css files will still automatically be added after your bower files.
However this is still no silver bullet as this setup has 2 big caveats to it:
1 - The files that are added through bower-grunt have to be listed in bower.json's main array. If you see a file isn't being loaded you would expect to be, you must either edit that packages bower.json file OR add the dependency manually through grunt-bower's packageSpecific options.
2 - The order of bower files in the asset linker is currently alphabetical. My only recourse to adjust this order so far is tinkering around with an additional grunt task to manually re-order files prior to the rest of Sail's compileAssets task. However this one I'm confident there is something grunt-bower could do by supporting package copy ordering.
Note: the following answer is no longer completely relevant to the current version of SailsJS because there is no support for the linker folder as of SailsJS 0.10.
See: Sails not generating linker
Original answer:
I was able to figure out a solution for this, which is actually pretty simple. I had not realized you could configure where bower places it's files.
Create a .bowerrc file and change the directory where bower components are installed, in the case of Sailjs they should be put into the assets folder.
/*
* Create a file called .bowerrc and put the following in it.
* This file should be in the root directory of the sails app.
*/
{
"directory": "assets/linker/bower_components"
}
Sails will then use grunt to copy them to the .tmp/public/assets folder whenever a file is change. If you don't wish to have sails continually deleting and then recopying those files you can exclude them in the grunt file.
/*
* This is not necessary, but if you have a lot of components and don't want
* them constantly being deleted and copied at every file change you can update
* your Gruntfile.js with the below.
*/
clean: {
dev: ['.tmp/public/**',
'!.tmp/public',
'!.tmp/public/bower_components/**'],
build: ['www']
},
One tip on using requirejs with sails. By default you will get an error from the socket.io file since sails will load it without using requirejs. This will throw an error since socket.io supports amd style loading, more details here http://requirejs.org/docs/errors.html#mismatch.
The simplest way to fix this is to just comment out the lines near the end of the socket.io.js.
/*
* Comment the below out in the file assets/js/socket.io.js, if using requirejs
* and you don't want to modify the default sails setup or socket.io.
*/
if (typeof define === "function" && define.amd) {
define([], function () { return io; });
}
The other way would be to recode the sails files in assets/js named "socket.io.js", "sails.io.js" and app.js to be amd modules.
The simplest way I've found of achieving this is simply to add the individual Bower components to your tasks/pipeline.js file. For example, here's how you might add Modernizr:
// Client-side javascript files to inject in order
// (uses Grunt-style wildcard/glob/splat expressions)
var jsFilesToInject = [
// Load sails.io before everything else
'js/dependencies/sails.io.js',
// Dependencies like jQuery, or Angular are brought in here
'js/dependencies/**/*.js',
// =========================================================
// Modernizr:
'bower_components/modernizr/modernizr.js',
// =========================================================
// All of the rest of your client-side js files
// will be injected here in no particular order.
'js/**/*.js'
];
A link to bower_components/modernizr/modernizr.js then gets inserted in the <!--SCRIPTS--> placeholder in your layout template, and it also gets minified, etc, when you run sails lift --prod.
Sorry for my late.
I think include bower_components in linker it's a bad idea, because when you will lift sails, everything in it will be copied in .tmp and include in tags.
For example, if you have include Angular with bower, you will have two inclusions in your script: one for angular.js and one for angular.min.js. And having both is a mistake.
Here is my solution on my projects :
I have created a folder bower_component in my root directory.
I have added this line in my Gruntfile.js in the array files in copy:dev
{ '.tmp/public/linker/js/angular.js': './bower_components/angular/angular.js' }
And for each files I want to include, I need to manually add a new line in this array. I haven't find an another automatic solution. If someone finds a better solution... ;)
There is more than one approach to hooking up SailsJS and Bower.
A package for SailsJS that integrates Bower via a custom generator exists here:
https://www.npmjs.com/package/sails-generate-bower
There is one for Gulp as well.

Is there a way to include file in coffee script?

I'd like to know if there is a way to include a file in a coffee script.
Something like #include in C or require in PHP...
If you use coffeescript with node.js (e.g. when using the commandline tool coffee) then you can use node's require() function exactly as you would for a JS-file.
Say you want to include included-file.coffee in main.coffee:
In included-file.coffee: declare and export objects you want to export
someVar = ...
exports.someVar = someVar
In main.coffee you can then say:
someVar = require('included-file.coffee').someVar
This gives you clean modularization and avoids namespace conflicts when including external code.
How about coffeescript-concat?
coffeescript-concat is a utility that preprocesses and concatenates
CoffeeScript source files.
It makes it easy to keep your CoffeeScript code in separate units and
still run them easily. You can keep your source logically separated
without the frustration of putting it all together to run or embed in
a web page. Additionally, coffeescript-concat will give you a single
sourcefile that will easily compile to a single Javascript file.
Tl;DR: Browserify, possibly with a build tool like Grunt...
Solutions review
Build tool + import pre-processor
If what you want is a single JS file to be run in the browser, I recommend using a build tool like Grunt (or Gulp, or Cake, or Mimosa, or any other) to pre-process your Coffeescript, along with an include/require/import module that will concatenate included files into your compiled output, like one of these:
Browserify: probably the rising standard and my personal favourite, lets you to use Node's exports/require API in your code, then extracts and concatenates everything required into a browser includable file. Exists for Grunt, Gulp, Mimosa and probably most others . To this day I reckon it is probably the best solution if you're after compatibility both Node and the browser (and even otherwise)
Some Rails Sprocket-like solutions like grunt-sprockets-directives or gulp-include will also work in a consistent way with CSS pre-processors (though those generally have their own importing mechanisms)
Other solutions include grunt-includes or grunt-import
Standalone import pre-processor
If you'd rather avoid the extra-complexity of a build tool, you can use Browserify stand-alone, or alternatives not based on Node's require like coffeescript-concat or Coffee-Stir
[Not recommended] Asynchronous dynamic loading (AJAX + eval)
If you're writing exclusively for the browser and don't mind, or rather really want, your script being spread across several files fetched via AJAX, you can use a myriad of tools like:
yepnope.js or Modernizr's .load based on yepnope: Please note that yepnope is now deprecated by its maintainer, who recommend using build tools and concatenation instead of remote loading
RequireJS
HeadJS
jQuery's $.getScript
Vanilla AJAX + eval
your own implementation of AMD
You can try this library I made to solve this same problem coffee-stir
its very simple.
Just type #include and the name of the file that you want to include
#include MyBaseClass.coffee
For details
http://beastjavascript.github.io/Coffee-Stir/
I found that using "gulp-concat" to merge my coffee scripts before processing them did the trick. It can be easily installed to your project with npm.
npm install gulp-concat
Then edit your gulpfile.js:
var gulp = require('gulp')
,coffee = require('gulp-coffee')
,concat = require('gulp-concat');
gulp.task('coffee', function(){
gulp.src('src/*.coffee')
.pipe(concat('app.coffee')
.pipe(coffee({bare: true}).on('error', gulp.log))
.pipe(gulp.dest('build/')
})
This is the code I used to concatenate all my coffee scripts before gulp processed it into the final build Javascript. The only issue is the files are processed in alphabetical order. You can explicitly state which file to process to achieve your own file order, but you lose the flexibility of adding dynamic .coffee files.
gulp.src(['src/file3.coffee', 'src/file1.coffee', 'src/file2.coffee'])
.pipe(concat('app.coffee'))
.pipe(coffee({bare: true}).on('error', gulp.log))
.pipe(gulp.dest('build/')
gulp-concat as of February 25th, 2015 is available at this url.
Rails uses sprockets to do this, and this syntax has been adapted to https://www.npmjs.org/package/grunt-sprockets-directives. Works well for me.

Categories

Resources