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 class LogErrorManager extends BasicErrorManager {
087
088 @Override
089 public void println(CheckLevel checkLevel, JSError jsError) {
090 if (checkLevel == CheckLevel.ERROR) {
091 if (_log.isErrorEnabled()) {
092 _log.error(
093 jsError.format(checkLevel, _simpleMessageFormatter));
094 }
095 }
096 else if (checkLevel == CheckLevel.WARNING) {
097 if (_log.isWarnEnabled()) {
098 _log.warn(
099 jsError.format(checkLevel, _simpleMessageFormatter));
100 }
101 }
102 }
103
104 @Override
105 protected void printSummary() {
106 if (_log.isErrorEnabled() && (getErrorCount() > 0)) {
107 _log.error(_buildMessage());
108 }
109 else if (_log.isWarnEnabled() && (getWarningCount() > 0)) {
110 _log.warn(_buildMessage());
111 }
112 }
113
114 private String _buildMessage() {
115 return String.format(
116 "{0} error(s), {1} warning(s)", getErrorCount(),
117 getWarningCount());
118 }
119
120 private final MessageFormatter _simpleMessageFormatter =
121 new SimpleMessageFormatter();
122
123 }
124
125 private class SimpleMessageFormatter implements MessageFormatter {
126
127 @Override
128 public String formatError(JSError jsError) {
129 return String.format(
130 "(%s:%d): %s", jsError.sourceName, jsError.lineNumber,
131 jsError.description);
132 }
133
134 @Override
135 public String formatWarning(JSError jsError) {
136 return formatError(jsError);
137 }
138
139 }
140
141 }