UNPKG

6.97 kBJavaScriptView Raw
1"use strict";
2
3var path = require("path"),
4 grunt = require("grunt"),
5 _ = require("lodash"),
6 stringUtils = require("underscore.string"),
7 JsBeautifierTask = function(task) {
8 // Store reference to original task
9 this.task = task;
10
11 // Merge task options with defaults
12 this.options = task.options(JsBeautifierTask.DEFAULT_OPTIONS);
13 },
14 addJsNewLine = true,
15 jsBeautifyVersion = require("./jsBeautifyVersion");
16
17/**
18 * Default options that will be merged with options specified in
19 * the original task.
20 *
21 * @type {*}
22 */
23JsBeautifierTask.DEFAULT_OPTIONS = {
24 mode: "VERIFY_AND_WRITE",
25 dest: "",
26 js: {},
27 css: {},
28 html: {}
29};
30
31/**
32 * Static method for registering an instance of the task with Grunt.
33 *
34 * @param {*} grunt
35 */
36JsBeautifierTask.registerWithGrunt = function(grunt) {
37 grunt.registerMultiTask("jsbeautifier", "jsbeautifier.org for grunt", function() {
38 var task = new JsBeautifierTask(this);
39 task.run();
40 });
41};
42
43function getFileType(file, config) {
44 var fileType = null,
45 fileMapping = {
46 "js": config.js.fileTypes,
47 "css": config.css.fileTypes,
48 "html": config.html.fileTypes
49 };
50 _.forEach(fileMapping, function(extensions, type) {
51 fileType = type;
52 return -1 === _.findIndex(extensions, function(ext) {
53 return stringUtils.endsWith(file, ext);
54 });
55 });
56 return fileType;
57}
58
59function getBeautifierSetup(file, config) {
60 var fileType = getFileType(file, config),
61 jsBeautify = require("js-beautify");
62 switch (fileType) {
63 case "js":
64 return [jsBeautify.js, config.js, addJsNewLine];
65 case "css":
66 return [jsBeautify.css, config.css];
67 case "html":
68 return [jsBeautify.html, config.html];
69 default:
70 grunt.fail.warn("Cannot beautify " + file.cyan + " (only js, css and html files can be beautified)");
71 return null;
72 }
73}
74
75function beautify(file, config, actionHandler) {
76 var setup = getBeautifierSetup(file, config);
77 if (!setup) {
78 return;
79 }
80
81 var beautifier = setup[0],
82 beautifyConfig = setup[1],
83 addNewLine = setup[2];
84
85 var original = grunt.file.read(file);
86 grunt.verbose.write("Beautifying " + file.cyan + "...");
87 var result = beautifier(original, beautifyConfig);
88
89 // jsbeautifier would skip the line terminator for js files
90 if (!result.charAt(result.length - 1).match(/[\n\r\u2028\u2029]/) && addNewLine) {
91 result += "\n";
92 }
93 grunt.verbose.ok();
94 /*jshint eqeqeq: false */
95 if (original != result) {
96 actionHandler(file, result);
97 }
98}
99
100JsBeautifierTask.prototype.run = function() {
101 var options = this.options;
102
103 var fileCount = 0,
104 changedFileCount = 0,
105 unVerifiedFiles = [];
106
107 function verifyActionHandler(src) {
108 unVerifiedFiles.push(src);
109 }
110
111 function verifyAndWriteActionHandler(src, result) {
112 grunt.verbose.writeln(options.dest + src);
113 grunt.file.write(options.dest + src, result);
114 changedFileCount++;
115 }
116
117 function convertCamelCaseToUnderScore(config) {
118 var underscoreKey;
119 _.forEach([config.js, config.css, config.html], function(conf) {
120 _.forEach(conf, function(value, key) {
121 underscoreKey = stringUtils.underscored(key);
122 if ("fileTypes" !== key && key !== underscoreKey) {
123 conf[underscoreKey] = value;
124 delete conf[key];
125 }
126 });
127 });
128 }
129
130 function getConfig() {
131 var config,
132 rcFile = require("rc")("jsbeautifier", {});
133
134 if (options.config || !_.isEqual(rcFile, {})) {
135 var baseConfig = options.config ? grunt.file.readJSON(path.resolve(options.config)) : rcFile;
136 config = {
137 js: {},
138 css: {},
139 html: {}
140 };
141 _.extend(config.js, baseConfig);
142 _.extend(config.css, baseConfig);
143 _.extend(config.html, baseConfig);
144 _.extend(config.js, baseConfig.js);
145 _.extend(config.css, baseConfig.css);
146 _.extend(config.html, baseConfig.html);
147 _.extend(config.js, options.js);
148 _.extend(config.css, options.css);
149 _.extend(config.html, options.html);
150 } else {
151 config = options;
152 }
153 config.js.fileTypes = _.union(config.js.fileTypes, [".js", ".json", '.es6']);
154 config.css.fileTypes = _.union(config.css.fileTypes, [".css"]);
155 config.html.fileTypes = _.union(config.html.fileTypes, [".html"]);
156
157 grunt.verbose.writeln("Beautify config before converting camelcase to underscore: " + JSON.stringify(config));
158
159 convertCamelCaseToUnderScore(config);
160
161 grunt.verbose.writeln("Using beautify config: " + JSON.stringify(config));
162 return config;
163 }
164
165 var sourceFiles = this.task.files;
166 if (sourceFiles && sourceFiles.length > 0) {
167 if (!_.isEmpty(options.dest)) {
168 grunt.verbose.writeln("All beautified files will be stored under \"" + options.dest + "\" folder");
169 if (!stringUtils.endsWith(options.dest, "/")) {
170 options.dest += "/";
171 }
172 }
173
174 grunt.verbose.writeln("Using mode=\"" + options.mode + "\"...");
175 var actionHandler = "VERIFY_ONLY" === options.mode ? verifyActionHandler : verifyAndWriteActionHandler,
176 config = getConfig(),
177 done = this.task.async();
178
179 /** Add new line for js file unless specified as false */
180 addJsNewLine = config.js.end_with_newline !== false;
181
182 jsBeautifyVersion(options.jsBeautifyVersion, function(error) {
183 if (error) {
184 grunt.fail.fatal("Unable to update js-beautify version to " + options.jsBeautifyVersion + " due to \n" + error);
185 return done(error);
186 }
187 var q = grunt.util.async.queue(function(src, callback) {
188 if (grunt.file.isDir(src)) {
189 callback();
190 return;
191 }
192
193 beautify(src, config, actionHandler);
194 fileCount++;
195 callback();
196 }, 10);
197
198 q.drain = function() {
199 if (unVerifiedFiles.length) {
200 grunt.fail.warn("The following files are not beautified:\n" + unVerifiedFiles.join("\n").cyan + "\n");
201 }
202 grunt.log.write("Beautified " + fileCount.toString().cyan + " files, changed " + changedFileCount.toString().cyan + " files...");
203 grunt.log.ok();
204 done();
205 };
206
207 sourceFiles.forEach(function(fileset) {
208 q.push(fileset.src);
209 });
210 });
211 }
212};
213
214module.exports = JsBeautifierTask;