/**
* Copyright (c) 2000-present Liferay, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*/
package com.liferay.portal.minifier;
import com.google.javascript.jscomp.BasicErrorManager;
import com.google.javascript.jscomp.CheckLevel;
import com.google.javascript.jscomp.Compiler;
import com.google.javascript.jscomp.CompilerOptions;
import com.google.javascript.jscomp.CompilerOptions.LanguageMode;
import com.google.javascript.jscomp.DiagnosticGroup;
import com.google.javascript.jscomp.DiagnosticGroups;
import com.google.javascript.jscomp.DiagnosticType;
import com.google.javascript.jscomp.JSError;
import com.google.javascript.jscomp.MessageFormatter;
import com.google.javascript.jscomp.PropertyRenamingPolicy;
import com.google.javascript.jscomp.SourceFile;
import com.google.javascript.jscomp.VariableRenamingPolicy;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.util.StringPool;
/**
* @author Carlos Sierra Andrés
*/
public class GoogleJavaScriptMinifier implements JavaScriptMinifier {
@Override
public String compress(String resourceName, String content) {
Compiler compiler = new Compiler(new LogErrorManager());
compiler.disableThreads();
SourceFile sourceFile = SourceFile.fromCode(resourceName, content);
CompilerOptions compilerOptions = new CompilerOptions();
compilerOptions.setLanguageIn(LanguageMode.ECMASCRIPT5);
compilerOptions.setWarningLevel(
DiagnosticGroups.NON_STANDARD_JSDOC, CheckLevel.OFF);
compilerOptions.setWarningLevel(
DiagnosticGroup.forType(
DiagnosticType.error("JSC_MISSING_PROVIDE_ERROR", "")),
CheckLevel.OFF);
compilerOptions.setWarningLevel(
DiagnosticGroup.forType(
DiagnosticType.error("JSC_NON_GLOBAL_DEFINE_INIT_ERROR", "")),
CheckLevel.OFF);
setCompileOptions(compilerOptions);
compiler.compile(
SourceFile.fromCode("extern", StringPool.BLANK), sourceFile,
compilerOptions);
return compiler.toSource();
}
protected void setCompileOptions(CompilerOptions compilerOptions) {
compilerOptions.checkGlobalThisLevel = CheckLevel.OFF;
compilerOptions.closurePass = true;
compilerOptions.coalesceVariableNames = true;
compilerOptions.collapseVariableDeclarations = true;
compilerOptions.convertToDottedProperties = true;
compilerOptions.deadAssignmentElimination = true;
compilerOptions.flowSensitiveInlineVariables = true;
compilerOptions.foldConstants = true;
compilerOptions.labelRenaming = true;
compilerOptions.removeDeadCode = true;
compilerOptions.optimizeArgumentsArray = true;
compilerOptions.setAssumeClosuresOnlyCaptureReferences(false);
compilerOptions.setInlineFunctions(CompilerOptions.Reach.LOCAL_ONLY);
compilerOptions.setInlineVariables(CompilerOptions.Reach.LOCAL_ONLY);
compilerOptions.setRenamingPolicy(
VariableRenamingPolicy.LOCAL, PropertyRenamingPolicy.OFF);
compilerOptions.setRemoveUnusedVariables(
CompilerOptions.Reach.LOCAL_ONLY);
}
private static final Log _log = LogFactoryUtil.getLog(
GoogleJavaScriptMinifier.class);
private static class SimpleMessageFormatter implements MessageFormatter {
@Override
public String formatError(JSError jsError) {
return String.format(
"(%s:%d): %s", jsError.sourceName, jsError.lineNumber,
jsError.description);
}
@Override
public String formatWarning(JSError jsError) {
return formatError(jsError);
}
}
private class LogErrorManager extends BasicErrorManager {
@Override
public void println(CheckLevel checkLevel, JSError jsError) {
if (checkLevel == CheckLevel.ERROR) {
_log.error(jsError.format(checkLevel, _simpleMessageFormatter));
}
else if (checkLevel == CheckLevel.WARNING) {
if (_log.isWarnEnabled()) {
_log.warn(
jsError.format(checkLevel, _simpleMessageFormatter));
}
}
}
@Override
protected void printSummary() {
if (getErrorCount() > 0) {
_log.error(_buildMessage());
}
else if (_log.isWarnEnabled() && (getWarningCount() > 0)) {
_log.warn(_buildMessage());
}
}
private String _buildMessage() {
return String.format(
"{0} error(s), {1} warning(s)", getErrorCount(),
getWarningCount());
}
private final MessageFormatter _simpleMessageFormatter =
new SimpleMessageFormatter();
}
}