View Javadoc
1   /*
2    *    Copyright 2009-2025 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    *       https://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   * @see HtmlCompressor#setJavaScriptCompressor(Compressor)
34   * @see <a href="http://developer.yahoo.com/yui/compressor/">Yahoo YUI Compressor</a>
35   */
36  public class YuiJavaScriptCompressor implements Compressor {
37  
38      /** The Constant logger. */
39      private static final Logger logger = LoggerFactory.getLogger(YuiJavaScriptCompressor.class);
40  
41      // YUICompressor default settings
42  
43      /** The no munge. */
44      private boolean noMunge;
45  
46      /** The preserve all semi colons. */
47      private boolean preserveAllSemiColons;
48  
49      /** The disable optimizations. */
50      private boolean disableOptimizations;
51  
52      /** The line break. */
53      private int lineBreak = -1;
54  
55      /** The error reporter. */
56      private ErrorReporter errorReporter = new DefaultErrorReporter();
57  
58      @Override
59      public String compress(String source) {
60  
61          StringWriter result = new StringWriter();
62          try {
63              JavaScriptCompressor compressor = new JavaScriptCompressor(new StringReader(source), errorReporter);
64              compressor.compress(result, lineBreak, !noMunge, false, preserveAllSemiColons, disableOptimizations);
65          } catch (IOException e) {
66              result.write(source);
67              logger.error("", e);
68          }
69          return result.toString();
70  
71      }
72  
73      /**
74       * Default <code>ErrorReporter</code> implementation that uses <code>System.err</code> stream for error reporting.
75       * Used by YUI Compressor to log errors during JavaScript compression.
76       *
77       * @see <a href="http://developer.yahoo.com/yui/compressor/">Yahoo YUI Compressor</a>
78       * @see <a href="http://www.mozilla.org/rhino/apidocs/org/mozilla/javascript/ErrorReporter.html">ErrorReporter
79       *      Interface</a>
80       */
81      public static class DefaultErrorReporter implements ErrorReporter {
82  
83          @Override
84          public void warning(String message, String sourceName, int line, String lineSource, int lineOffset) {
85              if (line < 0) {
86                  logger.error("[WARNING] HtmlCompressor: '{}' during JavaScript compression", message);
87              } else {
88                  logger.error("[WARNING] HtmlCompressor: '{}' at line [{}:{}] during JavaScript compression {}", message,
89                          line, lineOffset, lineSource != null ? ": " + lineSource : "");
90              }
91          }
92  
93          @Override
94          public void error(String message, String sourceName, int line, String lineSource, int lineOffset) {
95              if (line < 0) {
96                  logger.error("[ERROR] HtmlCompressor: '{}' during JavaScript compression", message);
97              } else {
98                  logger.error("[ERROR] HtmlCompressor: '{}' at line [{}:{}] during JavaScript compression {}", message,
99                          line, lineOffset, lineSource != null ? ": " + lineSource : "");
100             }
101         }
102 
103         @Override
104         public EvaluatorException runtimeError(String message, String sourceName, int line, String lineSource,
105                 int lineOffset) {
106             error(message, sourceName, line, lineSource, lineOffset);
107             return new EvaluatorException(message);
108         }
109     }
110 
111     /**
112      * Returns <code>true</code> if Yahoo YUI Compressor will only minify javascript without obfuscating local symbols.
113      * This corresponds to <code>--nomunge</code> command line option.
114      *
115      * @return <code>nomunge</code> parameter value used for JavaScript compression.
116      *
117      * @see <a href="http://developer.yahoo.com/yui/compressor/">Yahoo YUI Compressor</a>
118      */
119     public boolean isNoMunge() {
120         return noMunge;
121     }
122 
123     /**
124      * Tells Yahoo YUI Compressor to only minify javascript without obfuscating local symbols. This corresponds to
125      * <code>--nomunge</code> command line option. This option has effect only if JavaScript compression is enabled.
126      * Default is <code>false</code>.
127      *
128      * @param noMunge
129      *            set <code>true</code> to enable <code>nomunge</code> mode
130      *
131      * @see <a href="http://developer.yahoo.com/yui/compressor/">Yahoo YUI Compressor</a>
132      */
133     public void setNoMunge(boolean noMunge) {
134         this.noMunge = noMunge;
135     }
136 
137     /**
138      * Returns <code>true</code> if Yahoo YUI Compressor will preserve unnecessary semicolons during JavaScript
139      * compression. This corresponds to <code>--preserve-semi</code> command line option.
140      *
141      * @return <code>preserve-semi</code> parameter value used for JavaScript compression.
142      *
143      * @see <a href="http://developer.yahoo.com/yui/compressor/">Yahoo YUI Compressor</a>
144      */
145     public boolean isPreserveAllSemiColons() {
146         return preserveAllSemiColons;
147     }
148 
149     /**
150      * Tells Yahoo YUI Compressor to preserve unnecessary semicolons during JavaScript compression. This corresponds to
151      * <code>--preserve-semi</code> command line option. This option has effect only if JavaScript compression is
152      * enabled. Default is <code>false</code>.
153      *
154      * @param preserveAllSemiColons
155      *            set <code>true</code> to enable <code>preserve-semi</code> mode
156      *
157      * @see <a href="http://developer.yahoo.com/yui/compressor/">Yahoo YUI Compressor</a>
158      */
159     public void setPreserveAllSemiColons(boolean preserveAllSemiColons) {
160         this.preserveAllSemiColons = preserveAllSemiColons;
161     }
162 
163     /**
164      * Returns <code>true</code> if Yahoo YUI Compressor will disable all the built-in micro optimizations during
165      * JavaScript compression. This corresponds to <code>--disable-optimizations</code> command line option.
166      *
167      * @return <code>disable-optimizations</code> parameter value used for JavaScript compression.
168      *
169      * @see <a href="http://developer.yahoo.com/yui/compressor/">Yahoo YUI Compressor</a>
170      */
171     public boolean isDisableOptimizations() {
172         return disableOptimizations;
173     }
174 
175     /**
176      * Tells Yahoo YUI Compressor to disable all the built-in micro optimizations during JavaScript compression. This
177      * corresponds to <code>--disable-optimizations</code> command line option. This option has effect only if
178      * JavaScript compression is enabled. Default is <code>false</code>.
179      *
180      * @param disableOptimizations
181      *            set <code>true</code> to enable <code>disable-optimizations</code> mode
182      *
183      * @see <a href="http://developer.yahoo.com/yui/compressor/">Yahoo YUI Compressor</a>
184      */
185     public void setDisableOptimizations(boolean disableOptimizations) {
186         this.disableOptimizations = disableOptimizations;
187     }
188 
189     /**
190      * Returns number of symbols per line Yahoo YUI Compressor will use during JavaScript compression. This corresponds
191      * to <code>--line-break</code> command line option.
192      *
193      * @return <code>line-break</code> parameter value used for JavaScript compression.
194      *
195      * @see <a href="http://developer.yahoo.com/yui/compressor/">Yahoo YUI Compressor</a>
196      */
197     public int getLineBreak() {
198         return lineBreak;
199     }
200 
201     /**
202      * Tells Yahoo YUI Compressor to break lines after the specified number of symbols during JavaScript compression.
203      * This corresponds to <code>--line-break</code> command line option. This option has effect only if JavaScript
204      * compression is enabled. Default is <code>-1</code> to disable line breaks.
205      *
206      * @param lineBreak
207      *            set number of symbols per line
208      *
209      * @see <a href="http://developer.yahoo.com/yui/compressor/">Yahoo YUI Compressor</a>
210      */
211     public void setLineBreak(int lineBreak) {
212         this.lineBreak = lineBreak;
213     }
214 
215     /**
216      * Returns <code>ErrorReporter</code> used by YUI Compressor to log error messages during JavasSript compression.
217      *
218      * @return <code>ErrorReporter</code> used by YUI Compressor to log error messages during JavasSript compression
219      *
220      * @see <a href="http://developer.yahoo.com/yui/compressor/">Yahoo YUI Compressor</a>
221      * @see <a href="http://www.mozilla.org/rhino/apidocs/org/mozilla/javascript/ErrorReporter.html">Error Reporter
222      *      Interface</a>
223      */
224     public ErrorReporter getErrorReporter() {
225         return errorReporter;
226     }
227 
228     /**
229      * Sets <code>ErrorReporter</code> that YUI Compressor will use for reporting errors during JavaScript compression.
230      * If no <code>ErrorReporter</code> was provided {@link YuiJavaScriptCompressor.DefaultErrorReporter} will be used
231      * which reports errors to <code>System.err</code> stream.
232      *
233      * @param errorReporter
234      *            <code>ErrorReporter</code> that will be used by YUI Compressor
235      *
236      * @see YuiJavaScriptCompressor.DefaultErrorReporter
237      * @see <a href="http://developer.yahoo.com/yui/compressor/">Yahoo YUI Compressor</a>
238      * @see <a href="http://www.mozilla.org/rhino/apidocs/org/mozilla/javascript/ErrorReporter.html">ErrorReporter
239      *      Interface</a>
240      */
241     public void setErrorReporter(ErrorReporter errorReporter) {
242         this.errorReporter = errorReporter;
243     }
244 
245 }