UNPKG

4.24 kBJavaScriptView Raw
1/**
2 * grunt-nunjucks-2-html
3 * https://github.com/vitkarpov/grunt-nunjucks-2-html
4 *
5 * Copyright (c) 2014 Vit Karpov
6 * Licensed under the MIT license.
7 */
8
9'use strict'
10
11const nunjucks = require('nunjucks')
12const chalk = require('chalk')
13const path = require('path')
14
15module.exports = function (grunt) {
16 grunt.registerMultiTask('nunjucks', `Renders Nunjucks' templates to HTML`, function () {
17 // Declare async task
18 const completeTask = this.async()
19
20 // Get options and set defaults
21 const options = this.options({
22 watch: false,
23 paths: '',
24 configureEnvironment: false,
25 data: false,
26 preprocessData: false,
27 noCache: true
28 })
29
30 // Finish task if no files specified
31 if (!this.files.length) {
32 grunt.log.error('No files specified.')
33
34 // Finish task — nothing we can do without specified files
35 return completeTask()
36 }
37
38 // Warn in case of undefined data
39 if (!options.data) {
40 grunt.log.error(`Template's data is empty. Guess you've forget to specify data option.`)
41 }
42
43 // Arm Nunjucks
44 const env = nunjucks.configure(options.paths, options)
45
46 // Pass configuration to Nunjucks if specified
47 if (typeof options.configureEnvironment === 'function') {
48 options.configureEnvironment.call(this, env, nunjucks)
49 }
50
51 // Get number of files
52 const totalFiles = this.files.length
53 // Start counter for number of compiled files
54 let countCompiled = 0
55
56 // Run compilation asynchronously, wait for finish, then print results and complete task
57 const task = new Promise((resolve, reject) => {
58 // Iterate over all files' groups
59 this.files.forEach(file => {
60 // Set destination
61 let filedest = file.dest
62
63 // Check whether there are any source files
64 if (!file.src.length) {
65 grunt.log.error(`No source files specified for ${chalk.cyan(filedest)}.`)
66
67 // Skip to next file — nothing we can do without specified source files
68 return reject(new Error('For some destinations were not specified source files.'))
69 }
70
71 // Iterate over files' sources
72 file.src.forEach(src => {
73 // Construct absolute path to file for Nunjucks
74 let filepath = path.join(process.cwd(), src)
75
76 let data = {}
77 // Clone data
78 for (let i in options.data) {
79 if (options.data.hasOwnProperty(i)) {
80 data[i] = options.data[i]
81 }
82 }
83
84 // Preprocess data
85 if (options.data && typeof options.preprocessData === 'function') {
86 data = options.preprocessData.call(file, data)
87 }
88
89 // Asynchronously render templates with configurated Nunjucks environment
90 // and write to destination
91 env.render(filepath, data, (error, result) => {
92 // Catch errors, warn
93 if (error) {
94 grunt.log.error(error)
95 grunt.fail.warn('Failed to compile one of the source files.')
96 grunt.log.writeln()
97
98 // Prevent writing of failed to compile file, skip to next file
99 return reject(new Error('Failed to compile some source files.'))
100 }
101
102 // Write rendered template to destination
103 grunt.file.write(filedest, result)
104
105 // Debug process
106 grunt.verbose.ok(`File ${chalk.cyan(filedest)} created.`)
107 grunt.verbose.writeln()
108
109 countCompiled++
110 })
111 })
112 })
113
114 // Finish Promise
115 resolve()
116 })
117
118 // Print any errors from rejects
119 task.catch(error => {
120 if (error) {
121 grunt.log.writeln()
122 grunt.log.error(error)
123 grunt.log.writeln()
124 }
125 })
126
127 // Log number of processed templates
128 task.then(success => {
129 // Log number of processed templates
130 let logType = (countCompiled === totalFiles) ? 'ok' : 'error'
131 let countCompiledColor = (logType === 'ok') ? 'green' : 'red'
132 grunt.log[logType](`${chalk[countCompiledColor](countCompiled)}/${chalk.cyan(totalFiles)} ${grunt.util.pluralize(totalFiles, 'file/files')} compiled.`)
133 })
134
135 // Finish async task
136 completeTask()
137 })
138}