Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
162 changes: 128 additions & 34 deletions Minify.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import sublime, sublime_plugin, re, os, subprocess, platform, ntpath, shlex
import sublime, sublime_plugin, re, os, subprocess, platform, ntpath, shlex, json

PLUGIN_DIR = os.getcwd() if int(sublime.version()) < 3000 else os.path.dirname(__file__)
SUBL_ASYNC = callable(getattr(sublime, 'set_timeout_async', None))
Expand Down Expand Up @@ -39,6 +39,67 @@ def get_setting(self, key):
settings = sublime.load_settings('Minify.sublime-settings')
return settings.get(key)

def get_dir_settings(self, input_file):
config_dir = ntpath.split(input_file)[0]
config_file = config_dir + '/.minify'
config = {
'cssminifier': self.get_setting('cssminifier'),
'cleancss_options': self.get_setting('cleancss_options'),
'uglifycss_options': self.get_setting('uglifycss_options'),
'css_source_map': self.get_setting('css_source_map'),
'css_dist_directory': self.get_setting('css_dist_directory'),
'uglifyjs_command': self.get_setting('uglifyjs_command'),
'source_map': self.get_setting('source_map'),
'js_map_content': self.get_setting('js_map_content'),
'keep_comments': self.get_setting('keep_comments'),
'comments_to_keep': self.get_setting('comments_to_keep'),
'uglifyjs_options': self.get_setting('uglifyjs_options'),
'js_dist_directory': self.get_setting('js_dist_directory'),
'html-minifier_options': self.get_setting('html-minifier_options'),
'svgo_min_options': self.get_setting('svgo_min_options'),
'minjson_command': self.get_setting('minjson_command'),
'java_command': self.get_setting('java_command'),
'yui_compressor': self.get_setting('yui_compressor'),
'yui_charset': self.get_setting('yui_charset'),
'yui_line_break': self.get_setting('yui_line_break'),
'csso_command': self.get_setting('csso_command'),
'cleancss_command': self.get_setting('cleancss_command'),
'html-minifier_command':self.get_setting('html-minifier_command'),
'svgo_command': self.get_setting('svgo_command'),
'js-beautify_options': self.get_setting('js-beautify_options'),
'js-beautify_html_options': self.get_setting('js-beautify_html_options'),
'uglifyjs_pretty_options': self.get_setting('uglifyjs_pretty_options'),
'svgo_pretty_options': self.get_setting('svgo_pretty_options')
}
if self.get_setting('debug_mode'):
print('Minify: Config Directory: ' + str(config_dir))
if (os.path.exists(config_file)):
if (self.get_setting('debug_mode')):
print('Minify: Config File: ' + str(config_file));
try:
with open(config_file) as json_data:
config_file_content = json_data.read()
if (self.get_setting('debug_mode')):
print('Minify: Config JSON: ' + config_file_content)
config_json = json.loads(config_file_content)
if (self.get_setting('debug_mode')):
print('Minify: Initial configuration\n' + json.dumps(config));
for key, value in config_json.items():
if key in config:
config[key] = value
if (self.get_setting('debug_mode')):
print('Minify: Updated configuration\n' + json.dumps(config))
except ValueError as err:
err_msg = 'Please check your config file => ' + config_file + '\nPlease note that trailing commas are not allowed'
sublime.status_message(err_msg)
sublime.message_dialog(err_msg)
print('Minify Error: ' + err_msg)
if(self.get_setting('debug_mode')):
print('Minify Python Error: ' + str(err))
elif (self.get_setting('debug_mode')):
print('Minify: Config File ' + str(config_file) + ' not found');
return config

if not SUBL_ASYNC:
import threading

Expand Down Expand Up @@ -100,6 +161,7 @@ class MinifyClass(MinifyUtils):
def minify(self):
inpfile = self.view.file_name()
cwd = False
config = self.get_dir_settings(inpfile)
if type(inpfile).__name__ in ('str', 'unicode') and re.search(r'\.[^\.]+$', inpfile):
if self.view.is_dirty() and self.get_setting('save_first'):
self.view.run_command('save')
Expand All @@ -110,62 +172,93 @@ def minify(self):
if self.get_setting('debug_mode'):
print('Minify: Syntax: ' + str(syntax))
if re.search(r'\.js$', inpfile) or re.search(r'/JavaScript\.tmLanguage$', syntax):
cmd = self.fixStr(self.get_setting('uglifyjs_command') or 'uglifyjs').split()
cmd = self.fixStr(config.get('uglifyjs_command') or 'uglifyjs').split()
o_directory, rfile = ntpath.split(outfile)
if config.get('js_dist_directory'):
o_directory = os.path.dirname(o_directory) + '/dist'
if not os.path.isdir(o_directory):
os.mkdir(o_directory)
outfile = o_directory + '/' + os.path.basename(inpfile)
rfile = os.path.basename(outfile)
cmd.extend([self.quoteChrs(inpfile), '-o', self.quoteChrs(outfile), '-m', '-c'])
eo = self.get_setting('uglifyjs_options')
eo = config.get('uglifyjs_options')
if type(eo).__name__ in ('str', 'unicode'):
cmd.extend(self.fixStr(eo).split())
if self.get_setting('source_map'):
directory, rfile = ntpath.split(outfile)
mapfile = rfile or ntpath.basename(directory)
if config.get('source_map'):
directory, ifile = ntpath.split(inpfile)
mapfile = rfile or ifile
content = ''
if self.get_setting('js_map_content'):
basedir = self.quoteChrs(o_directory)
if self.get_setting('debug_mode'):
print('Minify: Directory: ' + str(directory))
print('Minify: rfile: ' + str(rfile))
print('Minify: mapfile: ' + str(mapfile))
print('Minify: basedir: ' + str(basedir))
if config.get('js_map_content'):
content = ',content="' + (self.quoteChrs(inpfile + '.map') if os.path.isfile(inpfile + '.map') else 'inline') + '"'
cmd.extend(['--source-map', "url='" + self.quoteChrs(mapfile) + ".map'" + content + ",root='',base='" + self.quoteChrs(directory) + "'"])
if self.get_setting('keep_comments'):
cmd.extend(['--source-map', "url='" + self.quoteChrs(mapfile) + ".map'" + content + ",root='',base='" + basedir + "'"])
if config.get('keep_comments'):
cmd.extend(['--comments'])
eo = self.get_setting('comments_to_keep')
eo = config.get('comments_to_keep')
if type(eo).__name__ in ('str', 'unicode'):
cmd.extend([eo])
elif re.search(r'\.json$', inpfile) or re.search(r'/JSON\.tmLanguage$', syntax):
cmd = self.fixStr(self.get_setting('minjson_command') or 'minjson').split()
cmd = self.fixStr(config.get('minjson_command') or 'minjson').split()
cmd.extend([self.quoteChrs(inpfile), '-o', self.quoteChrs(outfile)])
elif re.search(r'\.css$', inpfile) or re.search(r'/CSS\.tmLanguage$', syntax):
minifier = self.get_setting('cssminifier') or 'clean-css'
minifier = config.get('cssminifier') or 'clean-css'
if minifier == 'uglifycss':
cmd = self.fixStr(self.get_setting('uglifycss_command') or 'uglifycss').split()
eo = self.get_setting('uglifycss_options')
cmd = self.fixStr(config.get('uglifycss_command') or 'uglifycss').split()
eo = config.get('uglifycss_options')
if type(eo).__name__ in ('str', 'unicode'):
cmd.extend(self.fixStr(eo).split())
cmd.extend([self.quoteChrs(inpfile), '>', self.quoteChrs(outfile)])
elif minifier == 'yui':
cmd = self.fixStr(self.get_setting('java_command') or 'java').split()
yui_compressor = self.get_setting('yui_compressor') or 'yuicompressor-2.4.7.jar'
cmd = self.fixStr(config.get('java_command') or 'java').split()
yui_compressor = config.get('yui_compressor') or 'yuicompressor-2.4.7.jar'
cmd.extend(['-jar', PLUGIN_DIR + '/bin/' + str(yui_compressor), self.quoteChrs(inpfile), '-o', self.quoteChrs(outfile)])
eo = self.get_setting('yui_charset')
eo = config.get('yui_charset')
if type(eo).__name__ in ('str', 'unicode'):
cmd.extend(['--charset', eo])
eo = self.get_setting('yui_line_break')
eo = config.get('yui_line_break')
if type(eo).__name__ in ('int', 'str', 'unicode'):
cmd.extend(['--line-break', str(eo)])
elif minifier == 'csso':
cmd = self.fixStr(config.get('csso_command') or 'csso').split()
cmd.extend(['--input', self.quoteChrs(inpfile)])
cmd.extend(['--input-map', 'auto'])
if config.get('css_dist_directory'):
directory = os.path.dirname(inpfile) + '/dist'
if not os.path.isdir(directory):
os.mkdir(directory)
outfile = directory + '/' + os.path.basename(inpfile)
cmd.extend(['--output', self.quoteChrs(outfile)])
if config.get('css_source_map'):
cmd.extend(['--map', 'file'])
cwd = os.path.dirname(outfile)
else:
cmd = self.fixStr(self.get_setting('cleancss_command') or 'cleancss').split()
eo = self.get_setting('cleancss_options') or '-O2 --skip-rebase'
cmd = self.fixStr(config.get('cleancss_command') or 'cleancss').split()
eo = config.get('cleancss_options') or '-O2 --skip-rebase'
if config.get('css_dist_directory'):
directory = os.path.dirname(inpfile) + '/dist'
if not os.path.isdir(directory):
os.mkdir(directory)
outfile = directory + '/' + os.path.basename(inpfile)
if type(eo).__name__ in ('str', 'unicode'):
cmd.extend(self.fixStr(eo).split())
if self.get_setting('css_source_map'):
if config.get('css_source_map'):
cmd.extend(['--source-map'])
cwd = os.path.dirname(outfile)
cmd.extend(['-o', self.quoteChrs(outfile), self.quoteChrs(inpfile)])
elif re.search(r'\.html?$', inpfile) or re.search(r'/HTML\.tmLanguage$', syntax):
cmd = self.fixStr(self.get_setting('html-minifier_command') or 'html-minifier').split()
eo = self.get_setting('html-minifier_options') or '--collapse-boolean-attributes --collapse-whitespace --html5 --minify-css --minify-js --preserve-line-breaks --process-conditional-comments --remove-comments --remove-empty-attributes --remove-redundant-attributes --remove-script-type-attributes --remove-style-link-type-attributes'
cmd = self.fixStr(config.get('html-minifier_command') or 'html-minifier').split()
eo = config.get('html-minifier_options') or '--collapse-boolean-attributes --collapse-whitespace --html5 --minify-css --minify-js --preserve-line-breaks --process-conditional-comments --remove-comments --remove-empty-attributes --remove-redundant-attributes --remove-script-type-attributes --remove-style-link-type-attributes'
if type(eo).__name__ in ('str', 'unicode'):
cmd.extend(self.fixStr(eo).split())
cmd.extend(['-o', self.quoteChrs(outfile), self.quoteChrs(inpfile)])
elif re.search(r'\.svg$', inpfile):
cmd = self.fixStr(self.get_setting('svgo_command') or 'svgo').split()
eo = self.get_setting('svgo_min_options')
cmd = self.fixStr(config.get('svgo_command') or 'svgo').split()
eo = config.get('svgo_min_options')
if type(eo).__name__ in ('str', 'unicode'):
cmd.extend(self.fixStr(eo).split())
cmd.extend(['-i', self.quoteChrs(inpfile), '-o', self.quoteChrs(outfile)])
Expand All @@ -178,37 +271,38 @@ def minify(self):
class BeautifyClass(MinifyUtils):
def beautify(self):
inpfile = self.view.file_name()
config = self.get_dir_settings(inpfile)
if type(inpfile).__name__ in ('str', 'unicode') and re.search(r'\.[^\.]+$', inpfile):
if self.view.is_dirty() and self.get_setting('save_first'):
self.view.run_command('save')
outfile = re.sub(r'(?:\.min)?(\.[^\.]+)$', r'.beautified\1', inpfile, 1)
syntax = self.view.settings().get('syntax')
if re.search(r'\.js$', inpfile) or re.search(r'/JavaScript\.tmLanguage$', syntax):
cmd = self.fixStr(self.get_setting('uglifyjs_command') or 'uglifyjs').split()
cmd = self.fixStr(config.get('uglifyjs_command') or 'uglifyjs').split()
cmd.extend([self.quoteChrs(inpfile), '-o', self.quoteChrs(outfile), '--comments', 'all', '-b'])
eo = self.get_setting('uglifyjs_pretty_options')
eo = config.get('uglifyjs_pretty_options')
if type(eo).__name__ in ('str', 'unicode'):
cmd.extend(self.fixStr(eo).split())
elif re.search(r'\.json$', inpfile) or re.search(r'/JSON\.tmLanguage$', syntax):
cmd = self.fixStr(self.get_setting('minjson_command') or 'minjson').split()
cmd = self.fixStr(config.get('minjson_command') or 'minjson').split()
cmd.extend([self.quoteChrs(inpfile), '-o', self.quoteChrs(outfile), '-b'])
elif re.search(r'\.css$', inpfile) or re.search(r'/CSS\.tmLanguage$', syntax):
cmd = self.fixStr(self.get_setting('js-beautify_command') or 'js-beautify').split()
eo = self.get_setting('js-beautify_options')
cmd = self.fixStr(config.get('js-beautify_command') or 'js-beautify').split()
eo = config.get('js-beautify_options')
if type(eo).__name__ in ('str', 'unicode'):
cmd.extend(self.fixStr(eo).split())
cmd.extend(['--css', '-o', self.quoteChrs(outfile), self.quoteChrs(inpfile)])
elif re.search(r'\.html?$', inpfile) or re.search(r'/HTML\.tmLanguage$', syntax):
outfile = re.sub(r'(?:\.min)?(\.[^\.]+)$', r'.pretty\1', inpfile, 1)
cmd = self.fixStr(self.get_setting('js-beautify_command') or 'js-beautify').split()
eo = self.get_setting('js-beautify_html_options')
cmd = self.fixStr(config.get('js-beautify_command') or 'js-beautify').split()
eo = config.get('js-beautify_html_options')
if type(eo).__name__ in ('str', 'unicode'):
cmd.extend(self.fixStr(eo).split())
cmd.extend(['--html', '-o', self.quoteChrs(outfile), self.quoteChrs(inpfile)])
elif re.search(r'\.svg$', inpfile):
outfile = re.sub(r'(?:\.min)?(\.[^\.]+)$', r'.pretty\1', inpfile, 1)
cmd = self.fixStr(self.get_setting('svgo_command') or 'svgo').split()
eo = self.get_setting('svgo_pretty_options')
cmd = self.fixStr(config.get('svgo_command') or 'svgo').split()
eo = config.get('svgo_pretty_options')
if type(eo).__name__ in ('str', 'unicode'):
cmd.extend(self.fixStr(eo).split())
cmd.extend(['--pretty', '-i', self.quoteChrs(inpfile), '-o', self.quoteChrs(outfile)])
Expand Down