grunt-localizr
Advanced tools
Comparing version 0.1.4 to 0.2.0
@@ -8,6 +8,3 @@ 'use strict'; | ||
getName: function getName (filePath, root) { | ||
var fileInfo = {}, | ||
relative = module.exports.getRelative(filePath, root), | ||
paths; | ||
var relative = module.exports.getRelative(filePath, root); | ||
return relative.replace(path.extname(relative), ''); | ||
@@ -17,5 +14,4 @@ }, | ||
getRelative: function getRelative (filePath, root) { | ||
var relative = filePath.replace(root, ''); | ||
return relative.substr(1); | ||
return filePath.replace(root, '').substr(1); | ||
} | ||
}; |
{ | ||
"name": "grunt-localizr", | ||
"version": "0.1.4", | ||
"version": "0.2.0", | ||
"author": { | ||
@@ -13,2 +13,3 @@ "name": "Poornima Venkatakrishnan", | ||
"dependencies": { | ||
"bluebird": "^2.9.3", | ||
"concat-stream": "~1.4.3", | ||
@@ -18,11 +19,11 @@ "graceful-fs": "~2.0.2", | ||
"mkdirp": "~0.3.5", | ||
"q": "~1.0.0", | ||
"qlimit": "^0.1.1" | ||
}, | ||
"devDependencies": { | ||
"tape": "^2.12.0", | ||
"rimraf": "^2.2.6", | ||
"grunt": "^0.4.4", | ||
"grunt-force-task": "^1.0.0", | ||
"istanbul": "^0.2.6", | ||
"jshint": "^2.4.4", | ||
"grunt": "^0.4.4" | ||
"rimraf": "^2.2.6", | ||
"tape": "^2.12.0" | ||
}, | ||
@@ -29,0 +30,0 @@ "scripts": { |
@@ -8,2 +8,39 @@ grunt-localizr | ||
A grunt task to support i18n using localizr module. | ||
A grunt task to support i18n using localizr module for dust templates. i18n is solved the way kraken supports today using `.properties` files. | ||
The [localizr](https://github.com/krakenjs/localizr) module is a tool to apply localization to dust templates before rendering. | ||
This plugin uses that localizr module, and scans your project under the root app directory for | ||
* `.dust` files in `public/templates` | ||
* `.properties` content files for corresponding `.dust` files in `locales/` folder | ||
and puts the localized files in `tmp/` dir. | ||
For example: | ||
Localizing `public/templates/foo/bar.dust` with `locales/US/en/foo/bar.properties` will generate `tmp/US/en/foo/bar.dust` | ||
##Usage | ||
In your Gruntfile.js | ||
``` | ||
module.exports = function localizr(grunt) { | ||
// Load task | ||
grunt.loadNpmTasks('grunt-localizr'); | ||
// Options | ||
return { | ||
files: ['public/templates/**/*.dust'], | ||
options: { | ||
contentPath: ['locales/**/*.properties'] | ||
} | ||
}; | ||
}; | ||
``` | ||
## Using with kraken 1.0 apps | ||
If you use [generator-kraken](git@github.com:krakenjs/generator-kraken.git) for scaffolding your kraken apps, you will see | ||
that the generated `Gruntfile.js` will be automatically setting up the i18n task for you. | ||
@@ -21,3 +21,3 @@ /*───────────────────────────────────────────────────────────────────────────*\ | ||
var path = require('path'), | ||
Q = require('q'), | ||
BB = require('bluebird'), | ||
utils = require('../lib/utils'), | ||
@@ -29,2 +29,3 @@ mkdirp = require('mkdirp'), | ||
fs = require('fs'), | ||
localeList = require('../lib/localeList'), | ||
logger; | ||
@@ -44,7 +45,5 @@ | ||
grunt.registerMultiTask('localizr', 'A preprocessor for Dust.js templates.', function () { | ||
var done, options, contentPath, bundles, bundleRoot, filesSrc, | ||
var done, options, contentPath, bundleRoot, filesSrc, | ||
pathName = path.sep + '**' + path.sep + '*.properties', | ||
fileRoot = this.options().templateRoot || path.join('public', 'templates'), | ||
propFile = this.options().contentFile, | ||
promise; | ||
fileRoot = this.options().templateRoot || path.join('public', 'templates'); | ||
@@ -64,3 +63,2 @@ done = this.async(); | ||
//console.info('contentPath:', contentPath); | ||
filesSrc = this.filesSrc.map(correctPathSeparator); | ||
@@ -81,11 +79,22 @@ contentPath = contentPath.map(function (cp) { | ||
bundleRoot = Array.isArray(bundleRoot) ? bundleRoot[0] : bundleRoot; | ||
bundles = (grunt.file.expand(contentPath)).map(correctPathSeparator); | ||
Q.all(filesSrc.map(function (srcFile) { | ||
return processSrcDust(srcFile, bundles, bundleRoot, options); | ||
})).then(done); | ||
localeList(path.join(process.cwd(), bundleRoot), function (err, locales) { | ||
if (err) { | ||
logger.error('Terminating due to err', err); | ||
done(err); | ||
return; | ||
} | ||
BB.all(filesSrc.map(function (srcFile) { | ||
return processSrcDust(srcFile, locales, bundleRoot, options); | ||
})) | ||
.then(done) | ||
.catch(function (err) { | ||
logger.error('Terminating due to err', err); | ||
done(err); | ||
}); | ||
}); | ||
}); | ||
}; | ||
function processSrcDust(srcFile, bundles, bundleRoot, options) { | ||
var deferred = Q.defer(), | ||
function processSrcDust(srcFile, locales, bundleRoot, options) { | ||
var deferred = BB.pending(), | ||
fileBundles, | ||
@@ -97,8 +106,11 @@ name = utils.getName(srcFile, options.fileRoot), | ||
//get the bundles that correspond to this file | ||
fileBundles = bundles.filter(function (entry) { | ||
return (entry.indexOf(propName) !== -1); | ||
}); | ||
fileBundles = locales.map(function (entry) { | ||
return path.join(bundleRoot, entry, propName); | ||
}).filter(function (entry) { | ||
return fs.existsSync(path.join(process.cwd(), entry)); | ||
}); | ||
if (fileBundles.length === 0) { | ||
dustPromises = dustPromises.concat(processWhenNoBundles(bundles, bundleRoot, srcFile, name, options)); | ||
dustPromises = dustPromises.concat(processWhenNoBundles(locales, srcFile, name, options)); | ||
@@ -108,3 +120,3 @@ } else { | ||
} | ||
Q.all(dustPromises).then(function () { | ||
BB.all(dustPromises).then(function () { | ||
deferred.resolve(); | ||
@@ -116,17 +128,7 @@ }); | ||
function processWhenNoBundles(bundles, bundleRoot, srcFile, name, options) { | ||
return bundles.map(function (entry) { | ||
var arr = entry.split(path.sep); | ||
arr.pop(); | ||
arr.shift(); | ||
if (arr.length > 2) { | ||
arr = arr.slice(0, 2); | ||
} | ||
return arr.join(path.sep); | ||
}).filter(function (entry, index, self) { | ||
return (self.indexOf(entry) === index); | ||
}).map(function (entry) { | ||
var destFile = path.join(process.cwd(), options.tmpDir, entry, name + '.dust'); | ||
return copy(srcFile, destFile); | ||
}); | ||
function processWhenNoBundles(locales, srcFile, name, options) { | ||
return locales.map(function (entry) { | ||
var destFile = path.join(process.cwd(), options.tmpDir, entry, name + '.dust'); | ||
return copy(srcFile, destFile); | ||
}); | ||
} | ||
@@ -148,6 +150,5 @@ | ||
}, | ||
deferred = Q.defer(); | ||
deferred = BB.pending(); | ||
srcFile = path.join(process.cwd(), srcFile); | ||
propFile = path.join(process.cwd(), propFile); | ||
destFile = path.join(process.cwd(), destFile); | ||
@@ -158,5 +159,6 @@ | ||
if (err) { | ||
deferred.reject(err); | ||
logger.error('Failed to generate', srcFile, ' from ', destFile, 'error', err, '\n'); | ||
deferred.resolve(); //we want to continue with compiling other templates | ||
logger.error('Failed to generate', destFile, ' from ', srcFile, 'error', err, '\n'); | ||
return; | ||
} | ||
@@ -166,16 +168,23 @@ var out = concat({ encoding: 'string' }, function (data) { | ||
if (err) { | ||
deferred.reject(err); | ||
logger.error('Failed to generate', srcFile, ' from ', destFile, 'error', err, '\n'); | ||
deferred.resolve(); //we want to continue with compiling other templates | ||
logger.error('Failed to generate', destFile, ' from ', srcFile, 'error', err, '\n'); | ||
return; | ||
} | ||
deferred.resolve(destFile); | ||
logger.write('Generated ', destFile, '\n'); | ||
deferred.resolve(destFile); | ||
}); | ||
}); | ||
localizr.createReadStream(opt).pipe(out); | ||
localizr.createReadStream(opt) | ||
.on('error', function (err) { | ||
logger.error('Error while localizing with ', srcFile, ' and ', propFile); | ||
deferred.resolve(); //we want to continue with the compiling other templates | ||
}) | ||
.pipe(out) | ||
.on('error', function (err) { | ||
logger.error('Error while localizing with ', srcFile, ' and ', propFile); | ||
deferred.resolve(); //we want to continue with compiling other templates | ||
}); | ||
}); | ||
return deferred.promise; | ||
@@ -185,3 +194,3 @@ } | ||
var copy = qlimit(function copy(srcFile, destFile) { | ||
var deferred = Q.defer(); | ||
var deferred = BB.pending(); | ||
mkdirp(path.dirname(destFile), function (err) { | ||
@@ -194,7 +203,7 @@ if (err) { | ||
fs.createReadStream(srcFile).pipe(fs.createWriteStream(destFile) | ||
.on('finish', function() { | ||
.on('finish', function () { | ||
logger.write('Generated ', destFile, '\n'); | ||
deferred.resolve(); | ||
}).on('error', function(err) { | ||
logger.write('Failed to generate', destFile, '\n'); | ||
}).on('error', function (err) { | ||
logger.error('Failed to generate', destFile, '\n'); | ||
deferred.reject(err); | ||
@@ -201,0 +210,0 @@ })); |
@@ -8,6 +8,7 @@ 'use strict'; | ||
grunt.loadNpmTasks('grunt-force-task'); | ||
test('Grunt-localizr', function (t) { | ||
process.chdir(path.join(process.cwd(), 'test', 'fixtures')); | ||
grunt.task.init = function() {}; | ||
require('../tasks/index')(grunt); | ||
@@ -24,3 +25,2 @@ t.test('test a localizr build', function(t) { | ||
require('../tasks/index')(grunt); | ||
grunt.tasks(['localizr'], {}, function(){ | ||
@@ -57,3 +57,2 @@ //verify the files exist | ||
require('../tasks/index')(grunt); | ||
grunt.tasks(['localizr'], {}, function(){ | ||
@@ -74,2 +73,50 @@ //verify the files exist | ||
}); | ||
t.test('test a localizr build with three templates same name/ different dir , 2 with .properties file, 1 with no .properties, ' + | ||
'also makes sure absence of a properties file for a locale does not break the build', function(t) { | ||
grunt.initConfig({ | ||
localizr: { | ||
files: ['cornercase/templates/**/*.dust'], | ||
options: { | ||
contentPath: ['cornercase/locales/**/*.properties'], | ||
templateRoot: 'cornercase/templates' | ||
} | ||
} | ||
}); | ||
grunt.tasks(['localizr'], {}, function(){ | ||
//verify the files exist | ||
t.equal(true, fs.existsSync('./tmp/US/en/test.dust')); | ||
t.equal(true, fs.existsSync('./tmp/US/en/nested1/test.dust')); | ||
t.equal(true, fs.existsSync('./tmp/US/en/nested2/test.dust')); | ||
t.equal(false, fs.existsSync('./tmp/US/fr/test.dust')); | ||
//verify they have expected content | ||
t.equal('<div>Hola</div>', fs.readFileSync('./tmp/US/es/test.dust', 'utf8')); | ||
t.equal('<div>I am translated to algo</div>', fs.readFileSync('./tmp/US/es/nested1/test.dust', 'utf8')); | ||
t.equal('<div>I am cool and don\'t need any pre tags</div>', fs.readFileSync('./tmp/US/en/nested2/test.dust', 'utf8')); | ||
rimraf('tmp', function() { | ||
t.end(); | ||
}); | ||
}); | ||
}); | ||
t.test('test wrong root path', function(t) { | ||
grunt.initConfig({ | ||
localizr: { | ||
files: ['errorcase/templates/**/*.dust'], | ||
options: { | ||
contentPath: ['errorcase/locales/**/*.properties'], | ||
templateRoot: 'errorcase/templates' | ||
} | ||
} | ||
}); | ||
grunt.tasks(['force:localizr'], {}, function() { | ||
t.end(); | ||
}); | ||
}); | ||
}); | ||
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
24640
28
371
46
0
6
5
+ Addedbluebird@^2.9.3
+ Addedbluebird@2.11.0(transitive)
+ Addedq@1.5.1(transitive)
- Removedq@~1.0.0
- Removedq@1.0.1(transitive)