Grunt custom targets - javascript

Let's say I have 3 target modes for grunt: quick, build and dist
I also have a custom target make-stuff:
grunt.registerTask('make-stuff', [
'someCSStask',
'someUtility',
'somePackage',
'isolatedTask' // More on this below
]);
...that runs in all 3 of the above target modes (quick, build, dist) like so:
grunt.registerTask('quick', [
'some-task1',
'make-stuff'
]);
grunt.registerTask('build', [
'some-task1',
'some-task2',
'make-stuff'
]);
grunt.registerTask('dist', [
'some-task3',
'build' // make-stuff gets ran here since we reference 'build'
]);
I would like to run make-stuff normally in each target mode, except quick, where I want it to ignore isolatedTask

If this is your setup, why not move 'isolatedTask' into build?
grunt.registerTask('build', [
'some-task1',
'some-task2',
'make-stuff',
'isolatedTask'
]);
Otherwise, try something like this
grunt.registerTask(
'isolatedTask',
'Isolated tasks for make-stuff, skip if target mode is quick.',
function() {
var target = this.args[0];
if (target === 'quick') { return; }
// logic here
}
);
grunt.registerTask(
'quick',
function() {
grunt.run.tasks([
...,
'isolatedTask:' + this.nameArgs
]);
}
);

Related

Logging in nodejs using bunyan logger, Print DEBUG, INFO, ERROR to same file

I have defined the logger.js as below:
var bunyan = require('bunyan');
var bunyanOpts = {
name: 'my-api',
streams: [
{
level: 'info',
path: 'logs/mylogs.log'
}
]
};
Using this I am only able to print info level logs , is there a way I can print Debug, trace, warn, error in the same file?
The level property of a stream configuration sets the minimum level for that particular log stream. In your case, only messages with a level of info or higher will be logged to the logfile.
If you want it to log messages with lower levels (trace being the lowest), you can change the minimum level in the configuration:
var bunyanOpts = {
name : 'my-api',
streams : [{
level : 'trace',
path : 'logs/mylogs.log'
}]
};
You can have multiple streams writing to the same file I think
var bunyanOpts = {
name: 'my-api',
streams: [
{
level: 'info',
path: 'logs/mylogs.log'
},
{
level: 'debug',
path: 'logs/mylogs.log'
},
]
};

Node.js conditional require

Consider plugin c is supported in recent versions of Node.
What would be the best way to conditionally load it?
module.exports = {
plugins: [
require("a"),
require("b"),
[require("c"), { default: false }] //only if node version > 0.11
]
};
Make sure you add the semver package as a dependenc, then:
var semver = require("semver")
var plugins = [
require("a"),
require("b"),
];
if(semver.gt(process.version, "0.11")){
plugins.push(require("c"));
}
module.exports = {
plugins: plugins
};
This code checks for the node version using process.version, and appends the required plugin to the list if it is supported.
If you want to make sure the major part of the version number is 0 and the minor part of the version number is greater than 11 you could use this
var sem_ver = process.version.replace(/[^0-9\.]/g, '').split('.');
if(parseInt(sem_ver[0], 10) == 0 && parseInt(sem_ver[1], 10) > 11)) {
// load it
}
What you want to do is check the process object. According to the documentation, it will give you an object like so:
console.log(process.versions);
{ http_parser: '1.0',
node: '0.10.4',
v8: '3.14.5.8',
ares: '1.9.0-DEV',
uv: '0.10.3',
zlib: '1.2.3',
modules: '11',
openssl: '1.0.1e' }
Then, simply process out the node property into a conditional if in your object.
You could use process.version:
var subver = parseFloat(process.version.replace(/v/, ''));
module.exports = {
plugins: [
require("a"),
require("b"),
(subver > 0.11) [require("c"), { default: false }]
]
};

generating templates with grunt - looking for a task

I've got an HTML file with following content:
<html>
<body>
<span>{{ secret }}</span>
</body>
</html>
I'm looking for a grunt task that could take this source file, take a map of values:
grunt.initConfig({
myTask: {
myTarget: {
src: ...
dest: ...
values: {
secret: 'ABC'
}
}
}
})
and generate output file:
<html>
<body>
<span>ABC</span>
</body>
</html>
Is there any task like this? I saw grunt-mustache-html but it forces lots of things to exist which I really don't need and I don't want to use it. I want simply to take a single mustache (or hbs or whatever), fill it with data from grunt-level object and dump the result into another HTML file, that's all.
You could try grunt-template which processed lo-dash templates. Here's a basic setup to solve your problem:
//Gruntfile.js
config.template = {
myTask: {
options: {
data: function () {
return {
secret: 'ABC'
};
}
},
files: {
'output.html: ['template.html.tpl']
}
}
};
//template.html.tpl
<html>
<body>
<span><%= secret %></span>
</body>
</html>
#1. One options is to make use of grunt.template utility (see lagerone's answer). With custom delimiters you can achieve pretty close result to what you want:
grunt.template.addDelimiters('myDelimiters', '{{', '}}');
In this case your template will have to use {{= secret }} tags.
#2. Another option is that you can always write you own simple task. In your case it can look like this:
grunt.initConfig({
myTask: {
options: {
data: {
secret: 'ABC'
},
src: 'index.html',
dest: 'index.output.html'
}
}
});
grunt.registerTask('myTask', function() {
var options = this.options(),
template = grunt.file.read(options.src);
var content = template.replace(/\{\{\s*(.*?)\s*\}\}/g, function(a, b) {
return typeof options.data[b] !== undefined ? options.data[b] : '';
});
grunt.file.write(options.dest, content);
});
grunt.registerTask('default', ['myTask']);
I have used grunt-include-replace in the past. Is easy to use. In your gruntfile you will create a task similar to this one (Example taken from official github repo):
grunt.initConfig({
includereplace: {
your_target: {
options: {
// Task-specific options go here.
},
// Files to perform replacements and includes with
src: '*.html',
// Destination directory to copy files to
dest: 'dist/'
}
}
})

Grunt.js templates: Use the name of the target in a task?

I'm trying to use the name of the target in a template. Should be simple enough, right?
My scenario is this:
copy:
{
all: {
src: 'commonFiles/**', dest: 'build/<%= grunt.???? =>/common'
},
apple: { ... },
orange:{ ... },
banana:{ ... },
...
}
grunt.registerTask('default', ['apple', 'orange', 'banana']);
grunt.registerTask('apple' , 'copy:all copy:apples ... ... ...');
grunt.registerTask('orange', 'copy:all copy:orange ... ... ...');
grunt.registerTask('banana', 'copy:all copy:banana ... ... ...');
grimt.registerTask(...);
...
many, many more fruit
I've scoured the docs, I've console.log'd grunt but found no string that is the parent task. The closest I found was grunt.task.current.name but that ends up being copy:all.
The goal would be to get a directory structure like this for all my fruit:
build/apple/common/...
build/orange/common/...
build/banana/common/...
build/.../common/...
...
commonFiles/...
I'm sending a fruit basked to whomever can figure this out.
A dynamic alias task would probably be better suited for this use case.
See http://gruntjs.com/frequently-asked-questions#dynamic-alias-tasks
grunt.initConfig({
buildDir: 'all',
copy: {
all: {
src: 'commonFiles/**',
dest: 'build/<%= buildDir =>/common',
},
apple: { ... },
orange:{ ... },
banana:{ ... },
},
});
grunt.registerTask('build', function(target) {
if (target == null) {
return grunt.warn('Build target must be specified, like build:apple.');
}
grunt.config('buildDir', target);
grunt.task.run('copy:' + target);
});

Different behavior of ExtJS application in debug and minified mode

I'm facing an strange behavior in an web application I'm currently working on. The interface is totally built with ExtJs 4. The application has two modes, Debug and Production.
In Debug mode, when user click a menu item, I load synchronously, the dependent Javascripts file. Something like this:
for ( var i = 0; i < config.dependency.length; i++ ) {
var element = document.createElement('script');
element.onload = callback;
element.onreadystatechange = function () {
if ( element.readyState == 'loaded' || element.readyState == 'complete' ) {
callback();
}
};
}
One of the module's javascript file is like this:
module.js
Ext.define('Company.view.system.Module', {
extend: 'Company.view.abstract.Panel',
alias: 'widget.system.module',
/**
* These "_items" are built into the Object in `Company.view.abstract.Panel`
* using: Ext.create(this._items[i].clazz, conf);
*
* I'm just omitting the whole business logic there
*/
_items: [{
flex: 2,
clazz: 'Company.view.system.module.Form'
}, {
flex: 5,
clazz: 'Company.view.system.module.HtmlEditor'
}]
});
Ext.define('Company.view.system.module.Form', {
extend: 'Company.view.abstract.Form',
alias: 'widget.system.module.form',
items: [{
xtype: 'fieldset',
title: 'Module Grid',
items: [{
xtype: 'system.module.grid'
}]
}]
});
Ext.define('Company.view.system.module.Grid', {
extend: 'Company.view.abstract.Grid',
alias: 'widget.system.module.grid',
columns: [{
...
}],
afterLayout: function() {
this.callParent(arguments);
alert('after layout');
}
});
Ext.define('Company.view.system.module.HtmlEditor', {
extend: 'Company.view.abstract.HtmlEditor',
alias: 'widget.system.module.htmleditor',
...
});
Everything's working as expected in Debug mode. But in Production mode, I load the whole Modules as a single generated-minified-obfuscated javascript file (modules.js) at start up (i.e. before the ViewPort is rendered), instead of loading dependent modules after menu click event.
In Production mode, every Items, which is instantiated using "xtype" (Company.view.system.module.Grid in the above sample), is not rendered at all!
Screenshots of Debug mode and Production Mode.
What do you think is going on here which I'm missing?
Update:
The problem lies with the Height of the GridPanel, as It was computed at runtime, from the browser's screen size. Hence when the component being instantiated, the Height was not computed yet! Silly mistake :)
I would try moving the system.module.grid definition before it's being used in the system.module.form.
I would advise from having two different versions. What's your reason for that?

Categories

Resources