UNPKG

3.35 kBJavaScriptView Raw
1'use strict';
2
3var grunt = require('../grunt');
4
5// The module to be exported.
6var template = module.exports = {};
7
8// External libs.
9template.date = require('dateformat');
10
11// Format today's date.
12template.today = function(format) {
13 var now = new Date();
14 if (process.env.SOURCE_DATE_EPOCH) {
15 now = new Date((process.env.SOURCE_DATE_EPOCH * 1000) + (now.getTimezoneOffset() * 60000));
16 }
17 return template.date(now, format);
18};
19
20// Template delimiters.
21var allDelimiters = {};
22
23// Initialize template delimiters.
24template.addDelimiters = function(name, opener, closer) {
25 var delimiters = allDelimiters[name] = {};
26 // Used by grunt.
27 delimiters.opener = opener;
28 delimiters.closer = closer;
29 // Generate RegExp patterns dynamically.
30 var a = delimiters.opener.replace(/(.)/g, '\\$1');
31 var b = '([\\s\\S]+?)' + delimiters.closer.replace(/(.)/g, '\\$1');
32 // Used by Lo-Dash.
33 delimiters.lodash = {
34 evaluate: new RegExp(a + b, 'g'),
35 interpolate: new RegExp(a + '=' + b, 'g'),
36 escape: new RegExp(a + '-' + b, 'g')
37 };
38};
39
40// The underscore default template syntax should be a pretty sane default for
41// the config system.
42template.addDelimiters('config', '<%', '%>');
43
44// Set Lo-Dash template delimiters.
45template.setDelimiters = function(name) {
46 // Get the appropriate delimiters.
47 var delimiters = allDelimiters[name in allDelimiters ? name : 'config'];
48 // Tell Lo-Dash which delimiters to use.
49 grunt.util._.extend(grunt.util._.templateSettings, delimiters.lodash);
50 // Return the delimiters.
51 return delimiters;
52};
53
54// Process template + data with Lo-Dash.
55template.process = function(tmpl, options) {
56 if (!options) { options = {}; }
57 // Set delimiters, and get a opening match character.
58 var delimiters = template.setDelimiters(options.delimiters);
59 // Clone data, initializing to config data or empty object if omitted.
60 var data = Object.create(options.data || grunt.config.data || {});
61 // Expose grunt so that grunt utilities can be accessed, but only if it
62 // doesn't conflict with an existing .grunt property.
63 if (!('grunt' in data)) { data.grunt = grunt; }
64 // Keep track of last change.
65 var last = tmpl;
66 try {
67 // As long as tmpl contains template tags, render it and get the result,
68 // otherwise just use the template string.
69 while (tmpl.indexOf(delimiters.opener) >= 0) {
70 tmpl = grunt.util._.template(tmpl, options)(data);
71 // Abort if template didn't change - nothing left to process!
72 if (tmpl === last) { break; }
73 last = tmpl;
74 }
75 } catch (e) {
76 // In upgrading to Lo-Dash (or Underscore.js 1.3.3), \n and \r in template
77 // tags now causes an exception to be thrown. Warn the user why this is
78 // happening. https://github.com/documentcloud/underscore/issues/553
79 if (String(e) === 'SyntaxError: Unexpected token ILLEGAL' && /\n|\r/.test(tmpl)) {
80 grunt.log.errorlns('A special character was detected in this template. ' +
81 'Inside template tags, the \\n and \\r special characters must be ' +
82 'escaped as \\\\n and \\\\r. (grunt 0.4.0+)');
83 }
84 // Slightly better error message.
85 e.message = 'An error occurred while processing a template (' + e.message + ').';
86 grunt.warn(e, grunt.fail.code.TEMPLATE_ERROR);
87 }
88 // Normalize linefeeds and return.
89 return grunt.util.normalizelf(tmpl);
90};