1 | 'use strict';
|
2 |
|
3 | var PLUGIN_NAME = 'gulp-nunjucks-api';
|
4 |
|
5 | var glob = require('glob');
|
6 | var gutil = require('gulp-util');
|
7 | var lodash = require('lodash');
|
8 | var nunjucks = require('nunjucks');
|
9 | var path = require('path');
|
10 | var requireNew = require('require-new');
|
11 | var through = require('through2');
|
12 |
|
13 |
|
14 |
|
15 | function configure(options) {
|
16 | var config = {
|
17 | context: {},
|
18 | extension: '.html',
|
19 | verbose: false
|
20 | };
|
21 | if (options === undefined || options === null)
|
22 | options = {};
|
23 | else
|
24 | options = lodash.cloneDeep(options);
|
25 |
|
26 | configureErrors(config, options);
|
27 | configureVerbosity(config, options);
|
28 | configureGlobals(config, options);
|
29 | configureLocals(config, options);
|
30 | configureContext(config, options);
|
31 | configureFiles(config, options);
|
32 | configureNunjucks(config, options);
|
33 |
|
34 | return config;
|
35 | }
|
36 |
|
37 | function configureContext(config, options) {
|
38 | var g = config.g;
|
39 | lodash.assign(config.context, g.data);
|
40 | lodash.assign(config.context, g.functions);
|
41 | }
|
42 |
|
43 | function configureErrors(config, options) {
|
44 | if ('errors' in options)
|
45 | config.errors = options.errors;
|
46 | else
|
47 | config.errors = true;
|
48 | delete options.errors;
|
49 | }
|
50 |
|
51 | function configureFiles(config, options) {
|
52 | if (options.extension)
|
53 | config.extension = options.extension;
|
54 | if (options.src)
|
55 | config.src = options.src;
|
56 | delete options.extension;
|
57 | delete options.src;
|
58 | }
|
59 |
|
60 | function configureGlobals(config, options) {
|
61 | var g = {};
|
62 | var og = options.globals || {};
|
63 | g.data = lodash.merge({}, og.data, options.data);
|
64 | g.extensions = lodash.merge({}, og.extensions, options.extensions);
|
65 | g.filters = lodash.merge({}, og.filters, options.filters);
|
66 | g.functions = lodash.merge({}, og.functions, options.functions);
|
67 | config.g = g;
|
68 | delete options.data;
|
69 | delete options.extensions;
|
70 | delete options.filters;
|
71 | delete options.functions;
|
72 | delete options.globals;
|
73 | }
|
74 |
|
75 | function configureLocals(config, options) {
|
76 | if (options.locals === true)
|
77 | config.locals = '<filename>.+(js|json)';
|
78 | else
|
79 | config.locals = options.locals;
|
80 | delete options.locals;
|
81 | }
|
82 |
|
83 | function configureNunjucks(config, options) {
|
84 | var env;
|
85 | var g = config.g;
|
86 | var filters = g.filters;
|
87 | var extensions = g.extensions;
|
88 | var name;
|
89 |
|
90 |
|
91 |
|
92 |
|
93 |
|
94 | if (options.watch === undefined)
|
95 | options.watch = false;
|
96 |
|
97 | config.env = nunjucks.configure(config.src, options);
|
98 |
|
99 | env = config.env;
|
100 | for (name in filters)
|
101 | env.addFilter(name, filters[name]);
|
102 | for (name in extensions)
|
103 | env.addExtension(name, extensions[name]);
|
104 | }
|
105 |
|
106 | function configureVerbosity(config, options) {
|
107 | config.verbose = options.verbose || config.verbose;
|
108 | config.vlog = config.verbose ? log : returnGulpUtil;
|
109 | delete options.verbose;
|
110 | }
|
111 |
|
112 |
|
113 |
|
114 |
|
115 |
|
116 | function createError(message, opt) {
|
117 | return new gutil.PluginError(PLUGIN_NAME, message, opt);
|
118 | }
|
119 |
|
120 | function handleError(config, sender, err, cb, opt) {
|
121 | config.vlog('Handling error: ' + err);
|
122 | var pluginErr = createError(err, opt);
|
123 | if (config.errors)
|
124 | sender.emit('error', pluginErr);
|
125 | return cb(pluginErr);
|
126 | }
|
127 |
|
128 | function log(message) {
|
129 | return gutil.log.apply(gutil, arguments);
|
130 | }
|
131 |
|
132 | function requireFile(config, filepath, result) {
|
133 | if (filepath === undefined || filepath === null)
|
134 | return false;
|
135 | try {
|
136 | result.obj = requireNew(filepath);
|
137 | return true;
|
138 | }
|
139 | catch (err) {
|
140 | config.vlog('File not found: ' + filepath);
|
141 | }
|
142 | return false;
|
143 | }
|
144 |
|
145 |
|
146 |
|
147 | function assignLocals(context, config, file) {
|
148 | var searchpath = path.dirname(file.path);
|
149 | var pfile = path.parse(file.path);
|
150 | var locals = String.prototype.replace.apply(config.locals, [
|
151 | '<filename>', pfile.base]);
|
152 | locals = String.prototype.replace.apply(locals, [
|
153 | '<filename_noext>', pfile.name]);
|
154 | var pattern = locals;
|
155 | config.vlog('Searching for locals with pattern:', pattern, 'in:', searchpath);
|
156 | var options = {
|
157 | cwd: searchpath,
|
158 | nodir: true
|
159 | };
|
160 | var found = glob.sync(pattern, options);
|
161 | var i, fullpath, result;
|
162 | config.vlog('Found:', found.length, 'locals files.');
|
163 | for (i = 0; i < found.length; i++) {
|
164 | fullpath = path.resolve(searchpath, found[i]);
|
165 | config.vlog('Using locals file:', found[i], 'fullpath:', fullpath);
|
166 | result = {};
|
167 | if (requireFile(config, fullpath, result))
|
168 | lodash.assign(context, result.obj);
|
169 | }
|
170 | }
|
171 |
|
172 | function plugin(options) {
|
173 | var config = configure(options);
|
174 |
|
175 | function render(file, enc, cb) {
|
176 | var context = lodash.cloneDeep(config.context);
|
177 | var env = config.env;
|
178 | var _this = this;
|
179 |
|
180 | if (file.isNull()) {
|
181 | this.push(file);
|
182 | return cb();
|
183 | }
|
184 | if (file.isStream())
|
185 | return handleError(config, _this, 'Streaming not supported', cb);
|
186 | if (file.data)
|
187 | lodash.assign(context, file.data);
|
188 | if (config.locals)
|
189 | assignLocals(context, config, file);
|
190 | config.vlog('Rendering nunjucks file.path:', file.path);
|
191 | env.render(file.path, context, function (err, result) {
|
192 | if (err)
|
193 | return handleError(config, _this, err, cb);
|
194 | file.contents = new Buffer(result);
|
195 | file.path = gutil.replaceExtension(file.path, config.extension);
|
196 | _this.push(file);
|
197 | cb();
|
198 | });
|
199 | }
|
200 | return through.obj(render);
|
201 | }
|
202 | module.exports = plugin;
|
203 | plugin.nunjucks = nunjucks;
|
204 |
|
205 | function returnGulpUtil() {
|
206 | return gutil;
|
207 | }
|