All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.jawr.web.minification.CSSMinifier Maven / Gradle / Ivy

Go to download

Javascript/CSS bundling and compressing tool for java web apps. By using jawr resources are automatically bundled together and optionally minified and gzipped. Jawr provides tag libraries to reference a generated bundle either by id or by using the name of any of its members.

There is a newer version: 3.9
Show newest version
/**
 * Copyright 2007-2012 Jordi Hernández Sellés, Ibrahim Chaehoi
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
 * except in compliance with the License. You may obtain a copy of the License at
 * 
 * 	http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software distributed under the
 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 * either express or implied. See the License for the specific language governing permissions
 * and limitations under the License.
 */
package net.jawr.web.minification;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import net.jawr.web.resource.bundle.factory.util.RegexUtil;

/**
 * Minifies CSS files by removing expendable whitespace and comments.
 * 
 * @author Jordi Hernández Sellés
 * @author ibrahim Chaehoi
 */
public class CSSMinifier {

	// This regex captures comments
	private static final String COMMENT_REGEX = "(/\\*[^*]*\\*+([^/][^*]*\\*+)*/)";

	// Captures CSS strings
	// private static final String QUOTED_CONTENT_REGEX =
	// "('(\\\\'|[^'])*?')|(\"(\\\\\"|[^\"])*?\")";
	private static final String QUOTED_CONTENT_REGEX = "([\"']).*?\\1"; 

	// A placeholder string to replace and restore CSS strings
	private static final String STRING_PLACEHOLDER = "______'JAWR_STRING'______";

	// Captured CSS rules (requires replacing CSS strings with a placeholder, or
	// quoted braces will fool it.
	private static final String RULES_REGEX = "([^\\{\\}]*)(\\{[^\\{\\}]*})";

	// Captures newlines and tabs
	private static final String NEW_LINE_TABS_REGEX = "\\r|\\n|\\t|\\f";

	// This regex captures, in order:
	// (\\s*\\{\\s*)|(\\s*\\}\\s*)|(\\s*\\(\\s*)|(\\s*;\\s*)|(\\s*\\))
	// brackets, parentheses,colons and semicolons and any spaces around them
	// (except spaces AFTER a parentheses closing
	// symbol),
	// and ( +) occurrences of one or more spaces.
	/**
	 * There is a special case when the space should not be removed when
	 * preceeded by and keyword. Ex: 
	 * 
	 * @media only screen and (max-width:767px){ } 
	 */
	private static final String SPACES_REGEX = "(?ims)(\\s*\\{\\s*)|(\\s*\\}\\s*)|((? strings = new ArrayList();
		final Matcher stringMatcher = QUOTED_CONTENT_PATTERN
				.matcher(compressed);

		compressed = new MatcherProcessorCallback() {
			String matchCallback(final Matcher matcher) {
				final String match = matcher.group();
				strings.add(match);
				return STRING_PLACEHOLDER;
			}
		}.processWithMatcher(stringMatcher);

		// Grab all rules and replace whitespace in selectors
		final Matcher rulesmatcher = RULES_PATTERN.matcher(compressed);
		compressed = new MatcherProcessorCallback() {
			String matchCallback(final Matcher matcher) {
				final String match = matcher.group(1);
				final String spaced = NEW_LINES_TAB_PATTERN
						.matcher(match.toString()).replaceAll(SPACE).trim();
				return spaced + matcher.group(2);
			}
		}.processWithMatcher(rulesmatcher);

		// Replace all linefeeds and tabs
		compressed = NEW_LINES_TAB_PATTERN.matcher(compressed).replaceAll(" ");

		// Match all empty space we can minify
		final Matcher matcher = SPACES_PATTERN.matcher(compressed);
		compressed = new MatcherProcessorCallback() {
			String matchCallback(final Matcher matcher) {
				String replacement = SPACE;
				final String match = matcher.group();

				if (match.indexOf(BRACKET_OPEN) != -1)
					replacement = BRACKET_OPEN;
				else if (match.indexOf(BRACKET_CLOSE) != -1)
					replacement = BRACKET_CLOSE;
				else if (match.indexOf(PAREN_OPEN) != -1)
					replacement = PAREN_OPEN;
				else if (match.indexOf(COLON) != -1)
					replacement = COLON;
				else if (match.indexOf(SEMICOLON) != -1)
					replacement = SEMICOLON;
				else if (match.indexOf(PAREN_CLOSE) != -1)
					replacement = PAREN_CLOSE;

				return replacement;
			}
		}.processWithMatcher(matcher);

		// Restore all Strings
		final Matcher restoreMatcher = STRING_PLACE_HOLDE_PATTERN
				.matcher(compressed);
		final Iterator it = strings.iterator();
		compressed = new MatcherProcessorCallback() {
			String matchCallback(final Matcher matcher) {

				final String replacement = it.next();
				return replacement;
			}
		}.processWithMatcher(restoreMatcher);

		return new StringBuffer(compressed);
	}
	
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy