piwi/grunt-nunjucks-render

View on GitHub
lib/loader.js

Summary

Maintainability
C
7 hrs
Test Coverage
/**
 * grunt-nunjucks-render
 * https://github.com/piwi/grunt-nunjucks-render
 *
 * Copyright (c) 2015 Pierre Cassat
 * Licensed under the Apache 2.0 license.
 *
 * This is largely inspired by <https://github.com/adiktofsugar/grunt-nunjucks-alt/blob/master/lib/loaders.js>.
 */

'use strict';

var fs          = require('fs');
var path        = require('path');
var nunjucks    = require('nunjucks');
var nlib        = require('nunjucks/src/lib');
var loader      = require('nunjucks/src/loader');
var grunt       = require('grunt');
var lib         = require('./lib');

var FileSystemLoader = loader.extend({
    init: function(searchPaths, name, options) {
        this.pathsToNames   = {};
        this.name           = name;

        options = options || {};
        if (options.baseDir) {
            options.baseDir = lib.slashPath(options.baseDir);
        }
        this.options = options;

        if (!name) {
            throw new Error("You must provide a name for the FileSystemLoader");
        }

        if (searchPaths) {
            if (!nlib.isArray(searchPaths)) {
                searchPaths = [searchPaths];
            }
            this.searchPaths = searchPaths.map(path.normalize);
        } else {
            grunt.log.debug('>> no "searchPaths" defined, using auto search paths (will take much longer!!!)');
            this.searchPaths = ['.'];
        }
    },

    resolveFilepathToName: function (filepath) {
        var name = this.name;
        var resolvedName;

        // remove the baseDir part from the name resolution
        var baseDir = this.options.baseDir;
        if (baseDir) {
            if (filepath.substring(0, baseDir.length) === baseDir) {
                var oldfilepath = filepath;
                filepath = filepath.substring(baseDir.length);
            }
        }

        if (name instanceof RegExp) {
            var nameParts = filepath.match(name);
            if (!nameParts) {
                return false;
            }
            resolvedName = nameParts.slice(1).join('');
        } else if (name instanceof Function) {
            resolvedName = name(filepath);
        } else {
            throw new Error('Name must be a RegExp or a Function.');
        }

        return resolvedName;
    },

    getSource: function(name, ext) {
        var fullpath    = null;
        var searchPaths = this.searchPaths;
        var extensions  = this.options.extensions || [];
        var baseDir     = this.options.baseDir;

        // first in baseDir
        if (baseDir && fs.existsSync(baseDir + name)) {
            fullpath = baseDir + name;

        } else {
            // then in all searchPaths
            searchPathsLoop:
            for(var i=0; i<searchPaths.length; i++) {
                var stats = fs.statSync(searchPaths[i]);
                if (!stats.isDirectory()) {
                    continue;
                }

                var allPaths = fs.readdirSync(searchPaths[i]);
                for (var j =0; j<allPaths.length; j++) {
                    var resolvedAllPath = path.join(searchPaths[i], allPaths[j]);
                    if (this.resolveFilepathToName(resolvedAllPath) === name) {
                        fullpath = resolvedAllPath;
                        break searchPathsLoop;
                    }
                }
            }
        }

        if (!fullpath) {
            for (var k in extensions) {
                if (extensions[k]!==ext && name.slice(-(extensions[k].length)) !== extensions[k]) {
                    var source = this.getSource( name + extensions[k], extensions[k] );
                    if (source) {
                        return source;
                    }
                }
            }
            return null;
        }

        this.pathsToNames[fullpath] = name;

        var env = nunjucks.configure();
        env.addGlobal('template_path', fullpath);
        env.addGlobal('template_date', new Date());

        return { src: fs.readFileSync(fullpath, 'utf-8'),
                 path: fullpath,
                 noCache: true };
    }
});

module.exports.FileSystemLoader = FileSystemLoader;