View Javadoc
1   /*
2    *    Copyright 2009-2022 the original author or authors.
3    *
4    *    Licensed under the Apache License, Version 2.0 (the "License");
5    *    you may not use this file except in compliance with the License.
6    *    You may obtain a copy of the License at
7    *
8    *       http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *    Unless required by applicable law or agreed to in writing, software
11   *    distributed under the License is distributed on an "AS IS" BASIS,
12   *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *    See the License for the specific language governing permissions and
14   *    limitations under the License.
15   */
16  package com.googlecode.htmlcompressor.compressor;
17  
18  import com.yahoo.platform.yui.compressor.JavaScriptCompressor;
19  
20  import java.io.IOException;
21  import java.io.StringReader;
22  import java.io.StringWriter;
23  
24  import org.mozilla.javascript.ErrorReporter;
25  import org.mozilla.javascript.EvaluatorException;
26  import org.slf4j.Logger;
27  import org.slf4j.LoggerFactory;
28  
29  /**
30   * Basic JavaScript compressor implementation using <a href="http://developer.yahoo.com/yui/compressor/">Yahoo YUI
31   * Compressor</a> that could be used by {@link HtmlCompressor} for inline JavaScript compression.
32   *
33   * @author <a href="mailto:serg472@gmail.com">Sergiy Kovalchuk</a>
34   *
35   * @see HtmlCompressor#setJavaScriptCompressor(Compressor)
36   * @see <a href="http://developer.yahoo.com/yui/compressor/">Yahoo YUI Compressor</a>
37   */
38  public class YuiJavaScriptCompressor implements Compressor {
39  
40      /** The Constant logger. */
41      private static final Logger logger = LoggerFactory.getLogger(YuiJavaScriptCompressor.class);
42  
43      // YUICompressor default settings
44  
45      /** The no munge. */
46      private boolean noMunge;
47  
48      /** The preserve all semi colons. */
49      private boolean preserveAllSemiColons;
50  
51      /** The disable optimizations. */
52      private boolean disableOptimizations;
53  
54      /** The line break. */
55      private int lineBreak = -1;
56  
57      /** The error reporter. */
58      private ErrorReporter errorReporter = new DefaultErrorReporter();
59  
60      @Override
61      public String compress(String source) {
62  
63          StringWriter result = new StringWriter();
64          try {
65              JavaScriptCompressor compressor = new JavaScriptCompressor(new StringReader(source), errorReporter);
66              compressor.compress(result, lineBreak, !noMunge, false, preserveAllSemiColons, disableOptimizations);
67          } catch (IOException e) {
68              result.write(source);
69              logger.error("", e);
70          }
71          return result.toString();
72  
73      }
74  
75      /**
76       * Default <code>ErrorReporter</code> implementation that uses <code>System.err</code> stream for error reporting.
77       * Used by YUI Compressor to log errors during JavaScript compression.
78       *
79       * @author <a href="mailto:serg472@gmail.com">Sergiy Kovalchuk</a>
80       *
81       * @see <a href="http://developer.yahoo.com/yui/compressor/">Yahoo YUI Compressor</a>
82       * @see <a href="http://www.mozilla.org/rhino/apidocs/org/mozilla/javascript/ErrorReporter.html">ErrorReporter
83       *      Interface</a>
84       */
85      public static class DefaultErrorReporter implements ErrorReporter {
86  
87          @Override
88          public void warning(String message, String sourceName, int line, String lineSource, int lineOffset) {
89              if (line < 0) {
90                  logger.error("[WARNING] HtmlCompressor: '{}' during JavaScript compression", message);
91              } else {
92                  logger.error("[WARNING] HtmlCompressor: '{}' at line [{}:{}] during JavaScript compression {}", message,
93                          line, lineOffset, lineSource != null ? ": " + lineSource : "");
94              }
95          }
96  
97          @Override
98          public void error(String message, String sourceName, int line, String lineSource, int lineOffset) {
99              if (line < 0) {
100                 logger.error("[ERROR] HtmlCompressor: '{}' during JavaScript compression", message);
101             } else {
102                 logger.error("[ERROR] HtmlCompressor: '{}' at line [{}:{}] during JavaScript compression {}", message,
103                         line, lineOffset, lineSource != null ? ": " + lineSource : "");
104             }
105         }
106 
107         @Override
108         public EvaluatorException runtimeError(String message, String sourceName, int line, String lineSource,
109                 int lineOffset) {
110             error(message, sourceName, line, lineSource, lineOffset);
111             return new EvaluatorException(message);
112         }
113     }
114 
115     /**
116      * Returns <code>true</code> if Yahoo YUI Compressor will only minify javascript without obfuscating local symbols.
117      * This corresponds to <code>--nomunge</code> command line option.
118      *
119      * @return <code>nomunge</code> parameter value used for JavaScript compression.
120      *
121      * @see <a href="http://developer.yahoo.com/yui/compressor/">Yahoo YUI Compressor</a>
122      */
123     public boolean isNoMunge() {
124         return noMunge;
125     }
126 
127     /**
128      * Tells Yahoo YUI Compressor to only minify javascript without obfuscating local symbols. This corresponds to
129      * <code>--nomunge</code> command line option. This option has effect only if JavaScript compression is enabled.
130      * Default is <code>false</code>.
131      *
132      * @param noMunge
133      *            set <code>true</code> to enable <code>nomunge</code> mode
134      *
135      * @see <a href="http://developer.yahoo.com/yui/compressor/">Yahoo YUI Compressor</a>
136      */
137     public void setNoMunge(boolean noMunge) {
138         this.noMunge = noMunge;
139     }
140 
141     /**
142      * Returns <code>true</code> if Yahoo YUI Compressor will preserve unnecessary semicolons during JavaScript
143      * compression. This corresponds to <code>--preserve-semi</code> command line option.
144      *
145      * @return <code>preserve-semi</code> parameter value used for JavaScript compression.
146      *
147      * @see <a href="http://developer.yahoo.com/yui/compressor/">Yahoo YUI Compressor</a>
148      */
149     public boolean isPreserveAllSemiColons() {
150         return preserveAllSemiColons;
151     }
152 
153     /**
154      * Tells Yahoo YUI Compressor to preserve unnecessary semicolons during JavaScript compression. This corresponds to
155      * <code>--preserve-semi</code> command line option. This option has effect only if JavaScript compression is
156      * enabled. Default is <code>false</code>.
157      *
158      * @param preserveAllSemiColons
159      *            set <code>true</code> to enable <code>preserve-semi</code> mode
160      *
161      * @see <a href="http://developer.yahoo.com/yui/compressor/">Yahoo YUI Compressor</a>
162      */
163     public void setPreserveAllSemiColons(boolean preserveAllSemiColons) {
164         this.preserveAllSemiColons = preserveAllSemiColons;
165     }
166 
167     /**
168      * Returns <code>true</code> if Yahoo YUI Compressor will disable all the built-in micro optimizations during
169      * JavaScript compression. This corresponds to <code>--disable-optimizations</code> command line option.
170      *
171      * @return <code>disable-optimizations</code> parameter value used for JavaScript compression.
172      *
173      * @see <a href="http://developer.yahoo.com/yui/compressor/">Yahoo YUI Compressor</a>
174      */
175     public boolean isDisableOptimizations() {
176         return disableOptimizations;
177     }
178 
179     /**
180      * Tells Yahoo YUI Compressor to disable all the built-in micro optimizations during JavaScript compression. This
181      * corresponds to <code>--disable-optimizations</code> command line option. This option has effect only if
182      * JavaScript compression is enabled. Default is <code>false</code>.
183      *
184      * @param disableOptimizations
185      *            set <code>true</code> to enable <code>disable-optimizations</code> mode
186      *
187      * @see <a href="http://developer.yahoo.com/yui/compressor/">Yahoo YUI Compressor</a>
188      */
189     public void setDisableOptimizations(boolean disableOptimizations) {
190         this.disableOptimizations = disableOptimizations;
191     }
192 
193     /**
194      * Returns number of symbols per line Yahoo YUI Compressor will use during JavaScript compression. This corresponds
195      * to <code>--line-break</code> command line option.
196      *
197      * @return <code>line-break</code> parameter value used for JavaScript compression.
198      *
199      * @see <a href="http://developer.yahoo.com/yui/compressor/">Yahoo YUI Compressor</a>
200      */
201     public int getLineBreak() {
202         return lineBreak;
203     }
204 
205     /**
206      * Tells Yahoo YUI Compressor to break lines after the specified number of symbols during JavaScript compression.
207      * This corresponds to <code>--line-break</code> command line option. This option has effect only if JavaScript
208      * compression is enabled. Default is <code>-1</code> to disable line breaks.
209      *
210      * @param lineBreak
211      *            set number of symbols per line
212      *
213      * @see <a href="http://developer.yahoo.com/yui/compressor/">Yahoo YUI Compressor</a>
214      */
215     public void setLineBreak(int lineBreak) {
216         this.lineBreak = lineBreak;
217     }
218 
219     /**
220      * Returns <code>ErrorReporter</code> used by YUI Compressor to log error messages during JavasSript compression.
221      *
222      * @return <code>ErrorReporter</code> used by YUI Compressor to log error messages during JavasSript compression
223      *
224      * @see <a href="http://developer.yahoo.com/yui/compressor/">Yahoo YUI Compressor</a>
225      * @see <a href="http://www.mozilla.org/rhino/apidocs/org/mozilla/javascript/ErrorReporter.html">Error Reporter
226      *      Interface</a>
227      */
228     public ErrorReporter getErrorReporter() {
229         return errorReporter;
230     }
231 
232     /**
233      * Sets <code>ErrorReporter</code> that YUI Compressor will use for reporting errors during JavaScript compression.
234      * If no <code>ErrorReporter</code> was provided {@link YuiJavaScriptCompressor.DefaultErrorReporter} will be used
235      * which reports errors to <code>System.err</code> stream.
236      *
237      * @param errorReporter
238      *            <code>ErrorReporter</code> that will be used by YUI Compressor
239      *
240      * @see YuiJavaScriptCompressor.DefaultErrorReporter
241      * @see <a href="http://developer.yahoo.com/yui/compressor/">Yahoo YUI Compressor</a>
242      * @see <a href="http://www.mozilla.org/rhino/apidocs/org/mozilla/javascript/ErrorReporter.html">ErrorReporter
243      *      Interface</a>
244      */
245     public void setErrorReporter(ErrorReporter errorReporter) {
246         this.errorReporter = errorReporter;
247     }
248 
249 }