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 }