001
014
015 package com.liferay.portal.minifier;
016
017 import com.google.javascript.jscomp.BasicErrorManager;
018 import com.google.javascript.jscomp.CheckLevel;
019 import com.google.javascript.jscomp.Compiler;
020 import com.google.javascript.jscomp.CompilerOptions;
021 import com.google.javascript.jscomp.CompilerOptions.LanguageMode;
022 import com.google.javascript.jscomp.DiagnosticGroups;
023 import com.google.javascript.jscomp.JSError;
024 import com.google.javascript.jscomp.MessageFormatter;
025 import com.google.javascript.jscomp.PropertyRenamingPolicy;
026 import com.google.javascript.jscomp.SourceFile;
027 import com.google.javascript.jscomp.VariableRenamingPolicy;
028
029 import com.liferay.portal.kernel.log.Log;
030 import com.liferay.portal.kernel.log.LogFactoryUtil;
031 import com.liferay.portal.kernel.util.StringPool;
032
033
036 public class GoogleJavaScriptMinifier implements JavaScriptMinifier {
037
038 @Override
039 public String compress(String resourceName, String content) {
040 Compiler compiler = new Compiler(new LogErrorManager());
041
042 compiler.disableThreads();
043
044 SourceFile sourceFile = SourceFile.fromCode(resourceName, content);
045
046 CompilerOptions compilerOptions = new CompilerOptions();
047
048 compilerOptions.setLanguageIn(LanguageMode.ECMASCRIPT5);
049 compilerOptions.setWarningLevel(
050 DiagnosticGroups.NON_STANDARD_JSDOC, CheckLevel.OFF);
051
052 setCompileOptions(compilerOptions);
053
054 compiler.compile(
055 SourceFile.fromCode("extern", StringPool.BLANK), sourceFile,
056 compilerOptions);
057
058 return compiler.toSource();
059 }
060
061 protected void setCompileOptions(CompilerOptions compilerOptions) {
062 compilerOptions.checkGlobalThisLevel = CheckLevel.OFF;
063 compilerOptions.closurePass = true;
064 compilerOptions.coalesceVariableNames = true;
065 compilerOptions.collapseVariableDeclarations = true;
066 compilerOptions.convertToDottedProperties = true;
067 compilerOptions.deadAssignmentElimination = true;
068 compilerOptions.flowSensitiveInlineVariables = true;
069 compilerOptions.foldConstants = true;
070 compilerOptions.labelRenaming = true;
071 compilerOptions.removeDeadCode = true;
072 compilerOptions.optimizeArgumentsArray = true;
073
074 compilerOptions.setAssumeClosuresOnlyCaptureReferences(false);
075 compilerOptions.setInlineFunctions(CompilerOptions.Reach.LOCAL_ONLY);
076 compilerOptions.setInlineVariables(CompilerOptions.Reach.LOCAL_ONLY);
077 compilerOptions.setRenamingPolicy(
078 VariableRenamingPolicy.LOCAL, PropertyRenamingPolicy.OFF);
079 compilerOptions.setRemoveUnusedVariables(
080 CompilerOptions.Reach.LOCAL_ONLY);
081 }
082
083 private static final Log _log = LogFactoryUtil.getLog(
084 GoogleJavaScriptMinifier.class);
085
086 private static class SimpleMessageFormatter implements MessageFormatter {
087
088 @Override
089 public String formatError(JSError jsError) {
090 return String.format(
091 "(%s:%d): %s", jsError.sourceName, jsError.lineNumber,
092 jsError.description);
093 }
094
095 @Override
096 public String formatWarning(JSError jsError) {
097 return formatError(jsError);
098 }
099
100 }
101
102 private class LogErrorManager extends BasicErrorManager {
103
104 @Override
105 public void println(CheckLevel checkLevel, JSError jsError) {
106 if (checkLevel == CheckLevel.ERROR) {
107 if (_log.isErrorEnabled()) {
108 _log.error(
109 jsError.format(checkLevel, _simpleMessageFormatter));
110 }
111 }
112 else if (checkLevel == CheckLevel.WARNING) {
113 if (_log.isWarnEnabled()) {
114 _log.warn(
115 jsError.format(checkLevel, _simpleMessageFormatter));
116 }
117 }
118 }
119
120 @Override
121 protected void printSummary() {
122 if (_log.isErrorEnabled() && (getErrorCount() > 0)) {
123 _log.error(_buildMessage());
124 }
125 else if (_log.isWarnEnabled() && (getWarningCount() > 0)) {
126 _log.warn(_buildMessage());
127 }
128 }
129
130 private String _buildMessage() {
131 return String.format(
132 "{0} error(s), {1} warning(s)", getErrorCount(),
133 getWarningCount());
134 }
135
136 private final MessageFormatter _simpleMessageFormatter =
137 new SimpleMessageFormatter();
138
139 }
140
141 }