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