UNPKG

3.94 kBJavaScriptView Raw
1'use strict';
2
3var _ = require('lodash'),
4 listing = require('./listing'),
5 minifyEscapes = listing.minifyEscapes;
6
7/** Used to minify variables and string values to a single character. */
8var minNames = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
9_.each(minNames, function(value) { minNames.push(value + value); });
10
11/*----------------------------------------------------------------------------*/
12
13/**
14 * Pre-process `source` to prepare it for minification.
15 *
16 * @param {string} [source=''] The source to process.
17 * @param {Object} [options={}] The options object.
18 * @returns {string} Returns the processed source.
19 */
20function preprocess(source, options) {
21 source = _.toString(source);
22 options = _.cloneDeep(options);
23
24 // Remove unrecognized JSDoc tags so the Closure Compiler won't complain.
25 source = source.replace(/@(?:alias|category)\b.*/g, '');
26
27 if (options.isTemplate) {
28 return source;
29 }
30 // Remove whitespace from `_.template` related regexes.
31 source = source.replace(/(reEmptyString\w+\s*=)([\s\S]+?)(?=[,;]\n)/g, function(match, left, value) {
32 return left + value.replace(/\s|\\n/g, '');
33 });
34
35 // Remove whitespace from `_.template`.
36 source = source.replace(/^( *)function template\b[\s\S]+?\n\1}/m, function(snippet) {
37 // Remove whitespace from string literals.
38 snippet = snippet.replace(/^((?:[ "'$\w]+:)?\s*)"[^"\n\\]*?(?:\\.[^"\n\\]*?)*"|'[^'\n\\]*?(?:\\.[^'\n\\]*?)*'/gm, function(string, left) {
39 // Clip `string` after an object literal property name or leading spaces.
40 if (left) {
41 string = string.slice(left.length);
42 }
43 // Avoids removing the '\n' of the `stringEscapes` object.
44 string = string.replace(/\[object |delete |else (?!{)|function | in | instanceof |return\s+["'$\w]|throw |typeof |use strict|var |# |(["'])(?:\\n| )\1|\\\\n|\\n|\s+/g, function(match) {
45 return match == false || match == '\\n' ? '' : match;
46 });
47 // Unclip `string`.
48 return (left || '') + string;
49 });
50
51 // Remove newline from double-quoted strings.
52 snippet = snippet
53 .replace('"__p += \'"', '"__p+=\'"')
54 .replace('"\';\\n"', '"\';"');
55
56 // Add a newline back so "evaluate" delimiters can support single line comments.
57 snippet = snippet.replace('";__p+=\'"', '";\\n__p+=\'"');
58
59 // Remove default `sourceURL` value.
60 return snippet.replace(/^( *var\s+sourceURL\s*=\s*)[\s\S]+?(?=;\n$)/m, function(match, left) {
61 return left + "'sourceURL' in options ? '//# sourceURL=' + options.sourceURL + '\\n' : ''";
62 });
63 });
64
65 // Minify internal properties.
66 (function() {
67 var funcNames = [
68 'baseOrderBy',
69 'baseSortBy',
70 'compareMultiple',
71 ];
72
73 var props = [
74 'criteria',
75 'index',
76 'value'
77 ];
78
79 // Minify properties used in `funcNames` functions.
80 var snippets = source.match(RegExp('^( *)(?:var|function) +(?:' + funcNames.join('|') + ')\\b[\\s\\S]+?\\n\\1}', 'gm'));
81 _.each(snippets, function(snippet) {
82 var modified = snippet;
83 _.each(props, function(prop, index) {
84 var minName = minNames[index],
85 reDotProp = RegExp('\\.' + prop + '\\b', 'g'),
86 rePropName = RegExp("'" + prop + "'", 'g');
87
88 modified = modified
89 .replace(rePropName, "'" + minName + "'")
90 .replace(reDotProp, "['" + minName + "']");
91 });
92
93 // Replace with modified snippet.
94 source = source.replace(snippet, function() {
95 return modified;
96 });
97 });
98 }());
99
100 // Add brackets to escaped properties so the Closure Compiler won't mung them.
101 // See http://code.google.com/closure/compiler/docs/api-tutorial3.html#export.
102 return source.replace(RegExp('(["\'])(?:(?!\\1)[^\\n\\\\]|\\\\.)*\\1|\\.(' + minifyEscapes.join('|') + ')\\b', 'g'), function(match, quote, prop) {
103 return quote ? match : "['" + prop + "']";
104 });
105}
106
107module.exports = preprocess;