1 | "use strict";
|
2 |
|
3 | var path = require("path"),
|
4 | grunt = require("grunt"),
|
5 | _ = require("lodash"),
|
6 | stringUtils = require("underscore.string"),
|
7 | JsBeautifierTask = function(task) {
|
8 |
|
9 | this.task = task;
|
10 |
|
11 |
|
12 | this.options = task.options(JsBeautifierTask.DEFAULT_OPTIONS);
|
13 | },
|
14 | addJsNewLine = true,
|
15 | jsBeautifyVersion = require("./jsBeautifyVersion");
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 | JsBeautifierTask.DEFAULT_OPTIONS = {
|
24 | mode: "VERIFY_AND_WRITE",
|
25 | dest: "",
|
26 | js: {},
|
27 | css: {},
|
28 | html: {}
|
29 | };
|
30 |
|
31 |
|
32 |
|
33 |
|
34 |
|
35 |
|
36 | JsBeautifierTask.registerWithGrunt = function(grunt) {
|
37 | grunt.registerMultiTask("jsbeautifier", "jsbeautifier.org for grunt", function() {
|
38 | var task = new JsBeautifierTask(this);
|
39 | task.run();
|
40 | });
|
41 | };
|
42 |
|
43 | function 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 |
|
59 | function 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 |
|
75 | function 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 |
|
90 | if (!result.charAt(result.length - 1).match(/[\n\r\u2028\u2029]/) && addNewLine) {
|
91 | result += "\n";
|
92 | }
|
93 | grunt.verbose.ok();
|
94 |
|
95 | if (original != result) {
|
96 | actionHandler(file, result);
|
97 | }
|
98 | }
|
99 |
|
100 | JsBeautifierTask.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 |
|
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 |
|
214 | module.exports = JsBeautifierTask;
|