├── .gitignore ├── .mvn └── wrapper │ ├── MavenWrapperDownloader.java │ ├── maven-wrapper.jar │ └── maven-wrapper.properties ├── .travis.yml ├── CHANGELOG ├── LICENSE.txt ├── README-yuicompressor.txt ├── README.md ├── mvnw ├── mvnw.cmd ├── pom.xml └── src ├── assembly └── project.xml ├── it ├── demo01 │ ├── invoker.properties │ ├── pom.xml │ ├── src │ │ ├── main │ │ │ ├── resources-filtering │ │ │ │ ├── file_rf01.js │ │ │ │ └── file_rf02.js │ │ │ ├── resources-redirect │ │ │ │ ├── file_rr01.js │ │ │ │ └── file_rr02.js │ │ │ ├── resources │ │ │ │ ├── file_r01.js │ │ │ │ └── file_r02.js │ │ │ └── webapp │ │ │ │ ├── WEB-INF │ │ │ │ └── web.xml │ │ │ │ ├── index.jsp │ │ │ │ └── static │ │ │ │ ├── highlighter.js │ │ │ │ ├── jquery.pack.js │ │ │ │ ├── toAggregateAndRemove │ │ │ │ ├── bar.js │ │ │ │ └── foo.js │ │ │ │ ├── uni-form-generic.css │ │ │ │ ├── uni-form.css │ │ │ │ ├── uni-form.jquery.js │ │ │ │ └── zero.js │ │ └── test │ │ │ └── java │ │ │ └── ResourcesTest.java │ └── validate.groovy └── issue19 │ ├── invoker.properties │ ├── pom.xml │ ├── src │ └── main │ │ ├── filters │ │ └── dev.properties │ │ └── resources │ │ ├── file_r01.js │ │ ├── file_r02.js │ │ └── webapp.properties │ └── validate.groovy ├── main ├── java │ └── net_alchim31_maven_yuicompressor │ │ ├── Aggregation.java │ │ ├── BasicRhinoShell.java │ │ ├── ErrorReporter4Mojo.java │ │ ├── JSLintChecker.java │ │ ├── JSLintMojo.java │ │ ├── MojoSupport.java │ │ ├── SourceFile.java │ │ └── YuiCompressorMojo.java └── resources │ ├── META-INF │ └── m2e │ │ └── lifecycle-mapping-metadata.xml │ └── jslint.js ├── site ├── default-site.vm ├── resources │ ├── css │ │ ├── maven-base.css │ │ ├── maven-theme.css │ │ ├── print.css │ │ └── site.css │ └── images │ │ ├── close.gif │ │ ├── collapsed.gif │ │ ├── expanded.gif │ │ ├── external.png │ │ ├── icon_error_sml.gif │ │ ├── icon_info_sml.gif │ │ ├── icon_success_sml.gif │ │ ├── icon_warning_sml.gif │ │ ├── logos │ │ ├── build-by-maven-black.png │ │ ├── build-by-maven-white.png │ │ └── maven-feather.png │ │ └── newwindow.png ├── site.xml ├── template-site.vm └── xdoc │ ├── ex_aggregation.xml │ ├── ex_failOnWarning.xml │ ├── ex_gzip.xml │ ├── index.xml.vm │ ├── links.xml │ ├── usage_compress.xml │ └── usage_jslint.xml └── test └── java └── net_alchim31_maven_yuicompressor └── AggregationTestCase.java /.gitignore: -------------------------------------------------------------------------------- 1 | # use glob syntax. 2 | syntax: glob 3 | *.ser 4 | *.class 5 | *~ 6 | *.bak 7 | *.off 8 | *.old 9 | 10 | # eclipse conf file 11 | .settings 12 | .classpath 13 | .project 14 | .manager 15 | 16 | # idea 17 | *.iml 18 | *.iws 19 | *.ipr 20 | .idea 21 | 22 | # building 23 | target 24 | build 25 | null 26 | tmp* 27 | temp 28 | dist 29 | test-output 30 | build.log 31 | 32 | # other scm 33 | .svn 34 | .CVS 35 | .hg* 36 | 37 | # switch to regexp syntax. 38 | # syntax: regexp 39 | # ^\.pc/ 40 | 41 | 42 | /pom.xml.releaseBackup 43 | /release.properties 44 | -------------------------------------------------------------------------------- /.mvn/wrapper/MavenWrapperDownloader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2007-present 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 | import java.net.*; 17 | import java.io.*; 18 | import java.nio.channels.*; 19 | import java.util.Properties; 20 | 21 | public class MavenWrapperDownloader { 22 | 23 | private static final String WRAPPER_VERSION = "0.5.5"; 24 | /** 25 | * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. 26 | */ 27 | private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" 28 | + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar"; 29 | 30 | /** 31 | * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to 32 | * use instead of the default one. 33 | */ 34 | private static final String MAVEN_WRAPPER_PROPERTIES_PATH = 35 | ".mvn/wrapper/maven-wrapper.properties"; 36 | 37 | /** 38 | * Path where the maven-wrapper.jar will be saved to. 39 | */ 40 | private static final String MAVEN_WRAPPER_JAR_PATH = 41 | ".mvn/wrapper/maven-wrapper.jar"; 42 | 43 | /** 44 | * Name of the property which should be used to override the default download url for the wrapper. 45 | */ 46 | private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; 47 | 48 | public static void main(String args[]) { 49 | System.out.println("- Downloader started"); 50 | File baseDirectory = new File(args[0]); 51 | System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); 52 | 53 | // If the maven-wrapper.properties exists, read it and check if it contains a custom 54 | // wrapperUrl parameter. 55 | File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); 56 | String url = DEFAULT_DOWNLOAD_URL; 57 | if(mavenWrapperPropertyFile.exists()) { 58 | FileInputStream mavenWrapperPropertyFileInputStream = null; 59 | try { 60 | mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); 61 | Properties mavenWrapperProperties = new Properties(); 62 | mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); 63 | url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); 64 | } catch (IOException e) { 65 | System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); 66 | } finally { 67 | try { 68 | if(mavenWrapperPropertyFileInputStream != null) { 69 | mavenWrapperPropertyFileInputStream.close(); 70 | } 71 | } catch (IOException e) { 72 | // Ignore ... 73 | } 74 | } 75 | } 76 | System.out.println("- Downloading from: " + url); 77 | 78 | File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); 79 | if(!outputFile.getParentFile().exists()) { 80 | if(!outputFile.getParentFile().mkdirs()) { 81 | System.out.println( 82 | "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); 83 | } 84 | } 85 | System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); 86 | try { 87 | downloadFileFromURL(url, outputFile); 88 | System.out.println("Done"); 89 | System.exit(0); 90 | } catch (Throwable e) { 91 | System.out.println("- Error downloading"); 92 | e.printStackTrace(); 93 | System.exit(1); 94 | } 95 | } 96 | 97 | private static void downloadFileFromURL(String urlString, File destination) throws Exception { 98 | if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { 99 | String username = System.getenv("MVNW_USERNAME"); 100 | char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); 101 | Authenticator.setDefault(new Authenticator() { 102 | @Override 103 | protected PasswordAuthentication getPasswordAuthentication() { 104 | return new PasswordAuthentication(username, password); 105 | } 106 | }); 107 | } 108 | URL website = new URL(urlString); 109 | ReadableByteChannel rbc; 110 | rbc = Channels.newChannel(website.openStream()); 111 | FileOutputStream fos = new FileOutputStream(destination); 112 | fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); 113 | fos.close(); 114 | rbc.close(); 115 | } 116 | 117 | } 118 | -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidB/yuicompressor-maven-plugin/175bbbdde555f6e6eb4419f352818849da4f8665/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.3.9/apache-maven-3.3.9-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | sudo: false # faster builds 3 | jdk: 4 | - openjdk8 5 | cache: 6 | directories: 7 | - $HOME/.gradle/caches/ 8 | - $HOME/.gradle/wrapper/ 9 | - $HOME/.m2/repository/ 10 | 11 | script: "./mvnw package integration-test javadoc:jar site" 12 | 13 | -------------------------------------------------------------------------------- /CHANGELOG: -------------------------------------------------------------------------------- 1 | 2 | 1.3.1 3 | -------------------- 4 | 5 | + Upgraded YUI Compressor to version 2.4.7 with following changes: 6 | + Handle data urls without blowing up Java memory (regex) 7 | + Updated docs to reflect Java >= 1.5 required for CssCompressor 8 | + Fixed issue where we were breaking #AABBCC id selectors, with the #AABBCC -> #ABC color compression. 9 | 10 | + Changed default value for linebreakpos to -1, as currently default 0 have a special meaning (Fixed #31) 11 | 12 | YUI Compressor README: 13 | Some source control tools don't like files containing lines longer than, 14 | say 8000 characters. The linebreak option is used in that case to split 15 | long lines after a specific column. It can also be used to make the code 16 | more readable, easier to debug (especially with the MS Script Debugger) 17 | Specify 0 to get a line break after each semi-colon in JavaScript, and 18 | after each rule in CSS. 19 | 20 | + Added detailed CHANGELOG -------------------------------------------------------------------------------- /README-yuicompressor.txt: -------------------------------------------------------------------------------- 1 | ============================================================================== 2 | YUI Compressor 3 | ============================================================================== 4 | 5 | NAME 6 | 7 | YUI Compressor - The Yahoo! JavaScript and CSS Compressor 8 | 9 | SYNOPSIS 10 | 11 | Usage: java -jar yuicompressor-x.y.z.jar [options] [input file] 12 | 13 | Global Options 14 | -h, --help Displays this information 15 | --type Specifies the type of the input file 16 | --charset Read the input file using 17 | --line-break Insert a line break after the specified column number 18 | -v, --verbose Display informational messages and warnings 19 | -o Place the output into or a file pattern. 20 | Defaults to stdout. 21 | 22 | JavaScript Options 23 | --nomunge Minify only, do not obfuscate 24 | --preserve-semi Preserve all semicolons 25 | --disable-optimizations Disable all micro optimizations 26 | 27 | DESCRIPTION 28 | 29 | The YUI Compressor is a JavaScript compressor which, in addition to removing 30 | comments and white-spaces, obfuscates local variables using the smallest 31 | possible variable name. This obfuscation is safe, even when using constructs 32 | such as 'eval' or 'with' (although the compression is not optimal is those 33 | cases) Compared to jsmin, the average savings is around 20%. 34 | 35 | The YUI Compressor is also able to safely compress CSS files. The decision 36 | on which compressor is being used is made on the file extension (js or css) 37 | 38 | GLOBAL OPTIONS 39 | 40 | -h, --help 41 | Prints help on how to use the YUI Compressor 42 | 43 | --line-break 44 | Some source control tools don't like files containing lines longer than, 45 | say 8000 characters. The linebreak option is used in that case to split 46 | long lines after a specific column. It can also be used to make the code 47 | more readable, easier to debug (especially with the MS Script Debugger) 48 | Specify 0 to get a line break after each semi-colon in JavaScript, and 49 | after each rule in CSS. 50 | 51 | --type js|css 52 | The type of compressor (JavaScript or CSS) is chosen based on the 53 | extension of the input file name (.js or .css) This option is required 54 | if no input file has been specified. Otherwise, this option is only 55 | required if the input file extension is neither 'js' nor 'css'. 56 | 57 | --charset character-set 58 | If a supported character set is specified, the YUI Compressor will use it 59 | to read the input file. Otherwise, it will assume that the platform's 60 | default character set is being used. The output file is encoded using 61 | the same character set. 62 | 63 | -o outfile 64 | 65 | Place output in file outfile. If not specified, the YUI Compressor will 66 | default to the standard output, which you can redirect to a file. 67 | Supports a filter syntax for expressing the output pattern when there are 68 | multiple input files. ex: 69 | java -jar yuicompressor.jar -o '.css$:-min.css' *.css 70 | ... will minify all .css files and save them as -min.css 71 | 72 | -v, --verbose 73 | Display informational messages and warnings. 74 | 75 | JAVASCRIPT ONLY OPTIONS 76 | 77 | --nomunge 78 | Minify only. Do not obfuscate local symbols. 79 | 80 | --preserve-semi 81 | Preserve unnecessary semicolons (such as right before a '}') This option 82 | is useful when compressed code has to be run through JSLint (which is the 83 | case of YUI for example) 84 | 85 | --disable-optimizations 86 | Disable all the built-in micro optimizations. 87 | 88 | NOTES 89 | 90 | + If no input file is specified, it defaults to stdin. 91 | 92 | + Supports wildcards for specifying multiple input files. 93 | 94 | + The YUI Compressor requires Java version >= 1.5. 95 | 96 | + It is possible to prevent a local variable, nested function or function 97 | argument from being obfuscated by using "hints". A hint is a string that 98 | is located at the very beginning of a function body like so: 99 | 100 | function fn (arg1, arg2, arg3) { 101 | "arg2:nomunge, localVar:nomunge, nestedFn:nomunge"; 102 | 103 | ... 104 | var localVar; 105 | ... 106 | 107 | function nestedFn () { 108 | .... 109 | } 110 | 111 | ... 112 | } 113 | 114 | The hint itself disappears from the compressed file. 115 | 116 | + C-style comments starting with /*! are preserved. This is useful with 117 | comments containing copyright/license information. For example: 118 | 119 | /*! 120 | * TERMS OF USE - EASING EQUATIONS 121 | * Open source under the BSD License. 122 | * Copyright 2001 Robert Penner All rights reserved. 123 | */ 124 | 125 | becomes: 126 | 127 | /* 128 | * TERMS OF USE - EASING EQUATIONS 129 | * Open source under the BSD License. 130 | * Copyright 2001 Robert Penner All rights reserved. 131 | */ 132 | 133 | MODIFIED RHINO FILES 134 | 135 | YUI Compressor uses a modified version of the Rhino library 136 | (http://www.mozilla.org/rhino/) The changes were made to support 137 | JScript conditional comments, preserved comments, unescaped slash 138 | characters in regular expressions, and to allow for the optimization 139 | of escaped quotes in string literals. 140 | 141 | COPYRIGHT AND LICENSE 142 | 143 | Copyright (c) 2011 Yahoo! Inc. All rights reserved. 144 | The copyrights embodied in the content of this file are licensed 145 | by Yahoo! Inc. under the BSD (revised) open source license. 146 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # YUICompressor-maven-plugin 2 | 3 | [![Build Status](https://travis-ci.com/davidB/yuicompressor-maven-plugin.svg?branch=master)](https://travis-ci.com/davidB/yuicompressor-maven-plugin) 4 | 5 | ## Overview 6 | 7 | Maven's plugin to compress (minify/obfuscate/aggregate) JavaScript and CSS files using [YUI Compressor](http://developer.yahoo.com/yui/compressor/) 8 | 9 | ## Documentation 10 | 11 | Full documentation is available under following link: http://davidb.github.com/yuicompressor-maven-plugin/ 12 | 13 | Summary of the project history can be found in [CHANGELOG](https://github.com/davidB/yuicompressor-maven-plugin/blob/master/CHANGELOG) 14 | 15 | ## Build 16 | 17 | * `./mvnw package` : generate jar 18 | * `./mvnw site` : generate the plugin website 19 | * `./mvnw integration-test` : `./mvnw package` + run all integration test 20 | * `./mvnw integration-test -Dinvoker.test=demo01` : run integration test 'demo01' (against all configuration) useful for tuning/debug 21 | * `./mvnw install` : `./mvnw integration-test` + publish on local maven repository 22 | * `./mvnw install -Dmaven.test.skip=true` : ./mvnw install` without run of unit test and run of integration test 23 | * release : 24 | * `gpg --use-agent --armor --detach-sign --output $(mktemp) pom.xml` to avoid issue on macosx with gpg signature see [[MGPG-59] GPG Plugin: "gpg: signing failed: Inap 25 | propriate ioctl for device" - ASF JIRA](https://issues.apache.org/jira/browse/MGPG-59) 26 | * `./mvnw release:clean && ./mvnw release:prepare && ./mvnw release:perform` : to publish on staging repository via plugin 27 | * `./mvnw release:clean && ./mvnw release:prepare -Darguments="-DskipTests -Dmaven.test.skip=true" && ./mvnw release:perform -Darguments="-DskipTests -Dmaven.test.skip=true"` to publish without tests 28 | * `./mvnw site package source:jar javadoc:jar install:install gpg:sign deploy:deploy changes:announcement-generate -Dmaven.test.skip=true -DperformRelease=true` : man 29 | ual 30 | * connect to http://oss.sonatype.org/ close and release the request(about yuicompressor-maven-plugin) in staging repositories 31 | * browse the updated [mvnsite](https://davidb.github.io/yuicompressor-maven-plugin/) (check version into samples, ...) 32 | 33 | ## Issues 34 | 35 | Found a bug? Have an idea? Report it to the [issue tracker](https://github.com/davidB/yuicompressor-maven-plugin/issues?state=open) 36 | 37 | 38 | ## Developers 39 | 40 | * [David Bernard](https://github.com/davidB) 41 | * [Piotr Kuczynski](https://github.com/pkuczynski) 42 | 43 | 44 | ## License 45 | 46 | This project is available under the [Creative Commons GNU LGPL, Version 2.1](http://creativecommons.org/licenses/LGPL/2.1/). 47 | -------------------------------------------------------------------------------- /mvnw: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # ---------------------------------------------------------------------------- 3 | # Licensed to the Apache Software Foundation (ASF) under one 4 | # or more contributor license agreements. See the NOTICE file 5 | # distributed with this work for additional information 6 | # regarding copyright ownership. The ASF licenses this file 7 | # to you under the Apache License, Version 2.0 (the 8 | # "License"); you may not use this file except in compliance 9 | # with the License. You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | # ---------------------------------------------------------------------------- 20 | 21 | # ---------------------------------------------------------------------------- 22 | # Maven2 Start Up Batch script 23 | # 24 | # Required ENV vars: 25 | # ------------------ 26 | # JAVA_HOME - location of a JDK home dir 27 | # 28 | # Optional ENV vars 29 | # ----------------- 30 | # M2_HOME - location of maven2's installed home dir 31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven 32 | # e.g. to debug Maven itself, use 33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files 35 | # ---------------------------------------------------------------------------- 36 | 37 | if [ -z "$MAVEN_SKIP_RC" ] ; then 38 | 39 | if [ -f /etc/mavenrc ] ; then 40 | . /etc/mavenrc 41 | fi 42 | 43 | if [ -f "$HOME/.mavenrc" ] ; then 44 | . "$HOME/.mavenrc" 45 | fi 46 | 47 | fi 48 | 49 | # OS specific support. $var _must_ be set to either true or false. 50 | cygwin=false; 51 | darwin=false; 52 | mingw=false 53 | case "`uname`" in 54 | CYGWIN*) cygwin=true ;; 55 | MINGW*) mingw=true;; 56 | Darwin*) darwin=true 57 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home 58 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html 59 | if [ -z "$JAVA_HOME" ]; then 60 | if [ -x "/usr/libexec/java_home" ]; then 61 | export JAVA_HOME="`/usr/libexec/java_home`" 62 | else 63 | export JAVA_HOME="/Library/Java/Home" 64 | fi 65 | fi 66 | ;; 67 | esac 68 | 69 | if [ -z "$JAVA_HOME" ] ; then 70 | if [ -r /etc/gentoo-release ] ; then 71 | JAVA_HOME=`java-config --jre-home` 72 | fi 73 | fi 74 | 75 | if [ -z "$M2_HOME" ] ; then 76 | ## resolve links - $0 may be a link to maven's home 77 | PRG="$0" 78 | 79 | # need this for relative symlinks 80 | while [ -h "$PRG" ] ; do 81 | ls=`ls -ld "$PRG"` 82 | link=`expr "$ls" : '.*-> \(.*\)$'` 83 | if expr "$link" : '/.*' > /dev/null; then 84 | PRG="$link" 85 | else 86 | PRG="`dirname "$PRG"`/$link" 87 | fi 88 | done 89 | 90 | saveddir=`pwd` 91 | 92 | M2_HOME=`dirname "$PRG"`/.. 93 | 94 | # make it fully qualified 95 | M2_HOME=`cd "$M2_HOME" && pwd` 96 | 97 | cd "$saveddir" 98 | # echo Using m2 at $M2_HOME 99 | fi 100 | 101 | # For Cygwin, ensure paths are in UNIX format before anything is touched 102 | if $cygwin ; then 103 | [ -n "$M2_HOME" ] && 104 | M2_HOME=`cygpath --unix "$M2_HOME"` 105 | [ -n "$JAVA_HOME" ] && 106 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 107 | [ -n "$CLASSPATH" ] && 108 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"` 109 | fi 110 | 111 | # For Mingw, ensure paths are in UNIX format before anything is touched 112 | if $mingw ; then 113 | [ -n "$M2_HOME" ] && 114 | M2_HOME="`(cd "$M2_HOME"; pwd)`" 115 | [ -n "$JAVA_HOME" ] && 116 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" 117 | fi 118 | 119 | if [ -z "$JAVA_HOME" ]; then 120 | javaExecutable="`which javac`" 121 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then 122 | # readlink(1) is not available as standard on Solaris 10. 123 | readLink=`which readlink` 124 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then 125 | if $darwin ; then 126 | javaHome="`dirname \"$javaExecutable\"`" 127 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" 128 | else 129 | javaExecutable="`readlink -f \"$javaExecutable\"`" 130 | fi 131 | javaHome="`dirname \"$javaExecutable\"`" 132 | javaHome=`expr "$javaHome" : '\(.*\)/bin'` 133 | JAVA_HOME="$javaHome" 134 | export JAVA_HOME 135 | fi 136 | fi 137 | fi 138 | 139 | if [ -z "$JAVACMD" ] ; then 140 | if [ -n "$JAVA_HOME" ] ; then 141 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 142 | # IBM's JDK on AIX uses strange locations for the executables 143 | JAVACMD="$JAVA_HOME/jre/sh/java" 144 | else 145 | JAVACMD="$JAVA_HOME/bin/java" 146 | fi 147 | else 148 | JAVACMD="`which java`" 149 | fi 150 | fi 151 | 152 | if [ ! -x "$JAVACMD" ] ; then 153 | echo "Error: JAVA_HOME is not defined correctly." >&2 154 | echo " We cannot execute $JAVACMD" >&2 155 | exit 1 156 | fi 157 | 158 | if [ -z "$JAVA_HOME" ] ; then 159 | echo "Warning: JAVA_HOME environment variable is not set." 160 | fi 161 | 162 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher 163 | 164 | # traverses directory structure from process work directory to filesystem root 165 | # first directory with .mvn subdirectory is considered project base directory 166 | find_maven_basedir() { 167 | 168 | if [ -z "$1" ] 169 | then 170 | echo "Path not specified to find_maven_basedir" 171 | return 1 172 | fi 173 | 174 | basedir="$1" 175 | wdir="$1" 176 | while [ "$wdir" != '/' ] ; do 177 | if [ -d "$wdir"/.mvn ] ; then 178 | basedir=$wdir 179 | break 180 | fi 181 | # workaround for JBEAP-8937 (on Solaris 10/Sparc) 182 | if [ -d "${wdir}" ]; then 183 | wdir=`cd "$wdir/.."; pwd` 184 | fi 185 | # end of workaround 186 | done 187 | echo "${basedir}" 188 | } 189 | 190 | # concatenates all lines of a file 191 | concat_lines() { 192 | if [ -f "$1" ]; then 193 | echo "$(tr -s '\n' ' ' < "$1")" 194 | fi 195 | } 196 | 197 | BASE_DIR=`find_maven_basedir "$(pwd)"` 198 | if [ -z "$BASE_DIR" ]; then 199 | exit 1; 200 | fi 201 | 202 | ########################################################################################## 203 | # Extension to allow automatically downloading the maven-wrapper.jar from Maven-central 204 | # This allows using the maven wrapper in projects that prohibit checking in binary data. 205 | ########################################################################################## 206 | if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then 207 | if [ "$MVNW_VERBOSE" = true ]; then 208 | echo "Found .mvn/wrapper/maven-wrapper.jar" 209 | fi 210 | else 211 | if [ "$MVNW_VERBOSE" = true ]; then 212 | echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." 213 | fi 214 | if [ -n "$MVNW_REPOURL" ]; then 215 | jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar" 216 | else 217 | jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar" 218 | fi 219 | while IFS="=" read key value; do 220 | case "$key" in (wrapperUrl) jarUrl="$value"; break ;; 221 | esac 222 | done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" 223 | if [ "$MVNW_VERBOSE" = true ]; then 224 | echo "Downloading from: $jarUrl" 225 | fi 226 | wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" 227 | if $cygwin; then 228 | wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` 229 | fi 230 | 231 | if command -v wget > /dev/null; then 232 | if [ "$MVNW_VERBOSE" = true ]; then 233 | echo "Found wget ... using wget" 234 | fi 235 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then 236 | wget "$jarUrl" -O "$wrapperJarPath" 237 | else 238 | wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" 239 | fi 240 | elif command -v curl > /dev/null; then 241 | if [ "$MVNW_VERBOSE" = true ]; then 242 | echo "Found curl ... using curl" 243 | fi 244 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then 245 | curl -o "$wrapperJarPath" "$jarUrl" -f 246 | else 247 | curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f 248 | fi 249 | 250 | else 251 | if [ "$MVNW_VERBOSE" = true ]; then 252 | echo "Falling back to using Java to download" 253 | fi 254 | javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" 255 | # For Cygwin, switch paths to Windows format before running javac 256 | if $cygwin; then 257 | javaClass=`cygpath --path --windows "$javaClass"` 258 | fi 259 | if [ -e "$javaClass" ]; then 260 | if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then 261 | if [ "$MVNW_VERBOSE" = true ]; then 262 | echo " - Compiling MavenWrapperDownloader.java ..." 263 | fi 264 | # Compiling the Java class 265 | ("$JAVA_HOME/bin/javac" "$javaClass") 266 | fi 267 | if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then 268 | # Running the downloader 269 | if [ "$MVNW_VERBOSE" = true ]; then 270 | echo " - Running MavenWrapperDownloader.java ..." 271 | fi 272 | ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") 273 | fi 274 | fi 275 | fi 276 | fi 277 | ########################################################################################## 278 | # End of extension 279 | ########################################################################################## 280 | 281 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} 282 | if [ "$MVNW_VERBOSE" = true ]; then 283 | echo $MAVEN_PROJECTBASEDIR 284 | fi 285 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" 286 | 287 | # For Cygwin, switch paths to Windows format before running java 288 | if $cygwin; then 289 | [ -n "$M2_HOME" ] && 290 | M2_HOME=`cygpath --path --windows "$M2_HOME"` 291 | [ -n "$JAVA_HOME" ] && 292 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` 293 | [ -n "$CLASSPATH" ] && 294 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"` 295 | [ -n "$MAVEN_PROJECTBASEDIR" ] && 296 | MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` 297 | fi 298 | 299 | # Provide a "standardized" way to retrieve the CLI args that will 300 | # work with both Windows and non-Windows executions. 301 | MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" 302 | export MAVEN_CMD_LINE_ARGS 303 | 304 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 305 | 306 | exec "$JAVACMD" \ 307 | $MAVEN_OPTS \ 308 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ 309 | "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ 310 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" 311 | -------------------------------------------------------------------------------- /mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM http://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Maven2 Start Up Batch script 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM M2_HOME - location of maven2's installed home dir 28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending 30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | @REM e.g. to debug Maven itself, use 32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | @REM ---------------------------------------------------------------------------- 35 | 36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 37 | @echo off 38 | @REM set title of command window 39 | title %0 40 | @REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' 41 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 42 | 43 | @REM set %HOME% to equivalent of $HOME 44 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 45 | 46 | @REM Execute a user defined script before this one 47 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 48 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 49 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" 50 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" 51 | :skipRcPre 52 | 53 | @setlocal 54 | 55 | set ERROR_CODE=0 56 | 57 | @REM To isolate internal variables from possible post scripts, we use another setlocal 58 | @setlocal 59 | 60 | @REM ==== START VALIDATION ==== 61 | if not "%JAVA_HOME%" == "" goto OkJHome 62 | 63 | echo. 64 | echo Error: JAVA_HOME not found in your environment. >&2 65 | echo Please set the JAVA_HOME variable in your environment to match the >&2 66 | echo location of your Java installation. >&2 67 | echo. 68 | goto error 69 | 70 | :OkJHome 71 | if exist "%JAVA_HOME%\bin\java.exe" goto init 72 | 73 | echo. 74 | echo Error: JAVA_HOME is set to an invalid directory. >&2 75 | echo JAVA_HOME = "%JAVA_HOME%" >&2 76 | echo Please set the JAVA_HOME variable in your environment to match the >&2 77 | echo location of your Java installation. >&2 78 | echo. 79 | goto error 80 | 81 | @REM ==== END VALIDATION ==== 82 | 83 | :init 84 | 85 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 86 | @REM Fallback to current working directory if not found. 87 | 88 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 89 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 90 | 91 | set EXEC_DIR=%CD% 92 | set WDIR=%EXEC_DIR% 93 | :findBaseDir 94 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 95 | cd .. 96 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 97 | set WDIR=%CD% 98 | goto findBaseDir 99 | 100 | :baseDirFound 101 | set MAVEN_PROJECTBASEDIR=%WDIR% 102 | cd "%EXEC_DIR%" 103 | goto endDetectBaseDir 104 | 105 | :baseDirNotFound 106 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 107 | cd "%EXEC_DIR%" 108 | 109 | :endDetectBaseDir 110 | 111 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 112 | 113 | @setlocal EnableExtensions EnableDelayedExpansion 114 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 115 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 116 | 117 | :endReadAdditionalConfig 118 | 119 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 120 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" 121 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 122 | 123 | set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar" 124 | 125 | FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( 126 | IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B 127 | ) 128 | 129 | @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central 130 | @REM This allows using the maven wrapper in projects that prohibit checking in binary data. 131 | if exist %WRAPPER_JAR% ( 132 | if "%MVNW_VERBOSE%" == "true" ( 133 | echo Found %WRAPPER_JAR% 134 | ) 135 | ) else ( 136 | if not "%MVNW_REPOURL%" == "" ( 137 | SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar" 138 | ) 139 | if "%MVNW_VERBOSE%" == "true" ( 140 | echo Couldn't find %WRAPPER_JAR%, downloading it ... 141 | echo Downloading from: %DOWNLOAD_URL% 142 | ) 143 | 144 | powershell -Command "&{"^ 145 | "$webclient = new-object System.Net.WebClient;"^ 146 | "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ 147 | "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ 148 | "}"^ 149 | "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ 150 | "}" 151 | if "%MVNW_VERBOSE%" == "true" ( 152 | echo Finished downloading %WRAPPER_JAR% 153 | ) 154 | ) 155 | @REM End of extension 156 | 157 | @REM Provide a "standardized" way to retrieve the CLI args that will 158 | @REM work with both Windows and non-Windows executions. 159 | set MAVEN_CMD_LINE_ARGS=%* 160 | 161 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* 162 | if ERRORLEVEL 1 goto error 163 | goto end 164 | 165 | :error 166 | set ERROR_CODE=1 167 | 168 | :end 169 | @endlocal & set ERROR_CODE=%ERROR_CODE% 170 | 171 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost 172 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 173 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" 174 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" 175 | :skipRcPost 176 | 177 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 178 | if "%MAVEN_BATCH_PAUSE%" == "on" pause 179 | 180 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% 181 | 182 | exit /B %ERROR_CODE% 183 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4.0.0 3 | net.alchim31.maven 4 | yuicompressor-maven-plugin 5 | 1.5.2-SNAPSHOT 6 | maven-plugin 7 | 8 | YUI Compressor Maven Mojo 9 | 10 | To compress (Minify + Ofuscate) Javascript files and CSS 11 | files (using YUI Compressor from Julien Lecomte) and/or to check 12 | Javascript files with jslint. 13 | 14 | http://github.com/davidB/${project.artifactId} 15 | 2012 16 | 17 | 18 | Public domain (Unlicense) 19 | http://unlicense.org/ 20 | repo 21 | 22 | 23 | 24 | 25 | scm:git:git://github.com/davidB/${project.artifactId}.git 26 | scm:git:git@github.com:davidB/${project.artifactId}.git 27 | https://github.com/davidB/${project.artifactId}/ 28 | HEAD 29 | 30 | 31 | 32 | github 33 | http://github.com/davidB/${project.artifactId}/issues#issue/ 34 | 35 | 36 | 37 | 38 | david.bernard 39 | David Bernard 40 | +1 41 | 42 | Developer 43 | 44 | 45 | 46 | 47 | 48 | 49 | Piotr Kuczynski 50 | piotr.kuczynski@gmail.com 51 | 52 | Contributor 53 | 54 | +1 55 | 56 | 57 | Dave Hughes 58 | dlh3@sfu.ca 59 | 60 | Contributor 61 | 62 | -8 63 | 64 | 65 | Aneesh Joseph 66 | admin@coderplus.com 67 | 68 | Contributor 69 | 70 | +5.5 71 | 72 | 73 | 74 | 75 | 76 | 77 | sonatype-nexus-staging 78 | Nexus Release Repository 79 | https://oss.sonatype.org/service/local/staging/deploy/maven2/ 80 | 81 | 82 | sonatype-nexus-snapshots 83 | Sonatype Nexus Snapshots 84 | https://oss.sonatype.org/content/repositories/snapshots/ 85 | 86 | 87 | 88 | UTF-8 89 | github 90 | 1.8 91 | 1.8 92 | 3.0 93 | 3.3.9 94 | ${encoding} 95 | https://oss.sonatype.org/content/repositories/snapshots/ 96 | 97 | target/velocity.log 98 | 3.0 99 | 100 | 101 | 102 | ${maven.version} 103 | 104 | 105 | 114 | 115 | 116 | 117 | com.yahoo.platform.yui 118 | yuicompressor 119 | 120 | 121 | 2.4.7 122 | 123 | 124 | org.apache.maven 125 | maven-plugin-api 126 | ${maven.version} 127 | provided 128 | 129 | 130 | org.apache.maven 131 | maven-core 132 | ${maven.version} 133 | provided 134 | 135 | 136 | junit 137 | junit 138 | 4.12 139 | test 140 | 141 | 142 | org.sonatype.plexus 143 | plexus-build-api 144 | 0.0.7 145 | 146 | 147 | 148 | 149 | 150 | false 151 | 152 | 153 | true 154 | 155 | sonatype-nexus-snapshots 156 | Sonatype Nexus Snapshots 157 | https://oss.sonatype.org/content/repositories/snapshots 158 | 159 | 160 | 161 | false 162 | 163 | central 164 | Central Repository 165 | https://repo.maven.apache.org/maven2 166 | 167 | 168 | 169 | 170 | 171 | never 172 | 173 | 174 | false 175 | 176 | central 177 | Central Repository 178 | https://repo.maven.apache.org/maven2 179 | 180 | 181 | 182 | 183 | 184 | 185 | maven-changes-plugin 186 | 2.9 187 | 188 | 189 | maven-release-plugin 190 | 2.5.3 191 | 192 | 193 | maven-site-plugin 194 | 3.8.2 195 | 196 | 197 | maven-jxr-plugin 198 | 3.0.0 199 | 200 | 201 | org.codehaus.mojo 202 | taglist-maven-plugin 203 | 2.4 204 | 205 | 206 | maven-plugin-plugin 207 | 3.6.0 208 | 209 | 210 | maven-project-info-reports-plugin 211 | 3.0.0 212 | 213 | 214 | maven-deploy-plugin 215 | 2.8.2 216 | 217 | 218 | maven-install-plugin 219 | 2.5.2 220 | 221 | 222 | maven-source-plugin 223 | 3.1.0 224 | 225 | 226 | maven-javadoc-plugin 227 | 3.1.1 228 | 229 | 128m 230 | 512m 231 | true 232 | ${encoding} 233 | ${encoding} 234 | ${encoding} 235 | true 236 | true 237 | true 238 | true 239 | true 240 | false 241 | -missing 242 | 243 | http://java.sun.com/j2se/${maven.compiler.source}/docs/api/ 244 | http://slf4j.org/api/ 245 | http://commons.apache.org/lang/api-release/ 246 | http://commons.apache.org/io/api-release/ 247 | http://junit.sourceforge.net/javadoc/ 248 | 249 | 250 | 251 | 252 | ${project.groupId}.example*:${project.groupId}.util.internal* 253 | 254 | 255 | 256 | 257 | 258 | 259 | maven-site-plugin 260 | 3.8.2 261 | 262 | 263 | default-site 264 | site 265 | 266 | site 267 | 268 | 269 | 270 | default-deploy 271 | site-deploy 272 | 273 | deploy 274 | 275 | 276 | 277 | 278 | ${basedir}/src/site/template-site.vm 279 | 280 | 281 | 282 | maven-javadoc-plugin 283 | 284 | 285 | attach-javadocs 286 | 287 | jar 288 | 289 | 290 | 291 | 292 | 293 | 294 | org.codehaus.mojo 295 | animal-sniffer-maven-plugin 296 | 1.18 297 | 298 | 299 | org.codehaus.mojo.signature 300 | java18 301 | 1.0 302 | 303 | 304 | 305 | 306 | org.apache.maven.plugins 307 | maven-changes-plugin 308 | 309 | 310 | announcements 311 | 312 | David Bernard 313 | david.bernard.31@gmail.com 314 | 315 | 316 | 317 | 318 | org.sonatype.plugins 319 | nexus-staging-maven-plugin 320 | 1.6.8 321 | true 322 | 323 | sonatype-nexus-snapshots 324 | https://oss.sonatype.org/ 325 | false 326 | 327 | 328 | 329 | maven-release-plugin 330 | 2.5.3 331 | 332 | 333 | org.apache.maven.scm 334 | maven-scm-api 335 | 1.11.2 336 | compile 337 | 338 | 339 | org.apache.maven.scm 340 | maven-scm-provider-gitexe 341 | 1.11.2 342 | compile 343 | 344 | 345 | 346 | release 347 | install animal-sniffer:check site deploy nexus-staging:release 348 | false 349 | true 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | org.apache.maven.plugins 358 | maven-plugin-plugin 359 | 360 | 361 | org.apache.maven.plugins 362 | maven-project-info-reports-plugin 363 | 364 | 365 | org.apache.maven.plugins 366 | maven-javadoc-plugin 367 | 368 | 369 | org.apache.maven.plugins 370 | maven-jxr-plugin 371 | 372 | 373 | org.codehaus.mojo 374 | taglist-maven-plugin 375 | 376 | 377 | TODO 378 | FIXME 379 | @todo 380 | @deprecated 381 | 382 | 383 | 384 | 385 | maven-changes-plugin 386 | 387 | 388 | 389 | changes-report 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | integration-tests 399 | 400 | 401 | maven.test.skip 402 | !true 403 | 404 | 405 | 406 | 407 | 408 | maven-invoker-plugin 409 | 410 | 411 | 412 | false 413 | true 414 | src/it 415 | 416 | **/pom.xml 417 | 418 | setup.groovy 419 | validate.groovy 420 | 421 | 422 | 423 | integration-test 424 | 425 | install 426 | run 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | release 436 | 437 | 438 | performRelease 439 | true 440 | 441 | 442 | 443 | 444 | 445 | maven-gpg-plugin 446 | 1.6 447 | 448 | 449 | sign-artifacts 450 | verify 451 | 452 | sign 453 | 454 | 455 | 456 | 457 | 458 | maven-site-plugin 459 | 460 | 461 | com.github.github 462 | site-maven-plugin 463 | 0.12 464 | 465 | 466 | site 467 | 468 | site 469 | 470 | 471 | 472 | 473 | Building site for ${project.version} 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | -------------------------------------------------------------------------------- /src/assembly/project.xml: -------------------------------------------------------------------------------- 1 | 2 | project 3 | 4 | tar.bz2 5 | 6 | 7 | 8 | . 9 | 10 | 11 | target/** 12 | .hg/** 13 | .classpath 14 | .project 15 | .settings/** 16 | null/** 17 | test-output/** 18 | tmp/** 19 | dist/** 20 | build/** 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/it/demo01/invoker.properties: -------------------------------------------------------------------------------- 1 | invoker.goals=clean package -e 2 | invoker.goals.2=package 3 | -------------------------------------------------------------------------------- /src/it/demo01/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | it.sandbox 7 | yuicompressor-maven-plugin-demo 8 | war 9 | 1.0-SNAPSHOT 10 | yuicompressor-maven-plugin-demo Maven Webapp 11 | http://maven.apache.org 12 | 13 | 14 | junit 15 | junit 16 | 3.8.2 17 | test 18 | 19 | 20 | org.apache.commons 21 | commons-io 22 | 1.3.2 23 | test 24 | 25 | 26 | 27 | rf01 28 | rf02 29 | 30 | 31 | yuicompressor-maven-plugin-demo 32 | 33 | 34 | src/main/resources 35 | 36 | 37 | src/main/resources-filtering 38 | true 39 | 40 | 41 | src/main/resources-redirect 42 | redirect 43 | 44 | 45 | 46 | 47 | @project.groupId@ 48 | yuicompressor-maven-plugin 49 | @project.version@ 50 | 51 | 52 | 53 | jslint 54 | compress 55 | 56 | 57 | 58 | 59 | true 60 | false 61 | 62 | true 63 | true 64 | true 65 | 66 | **/*.pack.js 67 | **/compressed.css 68 | 69 | 70 | 71 | 72 | 73 | 74 | true 75 | ${project.build.directory}/${project.build.finalName}/static/all.js 76 | 77 | 78 | **/*.js 79 | 80 | 81 | 82 | **/*.pack.js 83 | **/compressed.css 84 | 85 | 86 | 87 | 88 | true 89 | 90 | true 91 | ${project.build.directory}/${project.build.finalName}/static/all-2.js 92 | 93 | 94 | toAggregateAndRemove/foo.js 95 | toAggregateAndRemove/bar.js 96 | 97 | 98 | 99 | 100 | 101 | 102 | org.apache.maven.plugins 103 | maven-war-plugin 104 | 105 | **/toAggregateAndRemove/** 106 | 107 | 108 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /src/it/demo01/src/main/resources-filtering/file_rf01.js: -------------------------------------------------------------------------------- 1 | // compression must remove me 2 | var artifactId="${pom.artifactId}"; 3 | var ${value.rf01}="rf01"; 4 | -------------------------------------------------------------------------------- /src/it/demo01/src/main/resources-filtering/file_rf02.js: -------------------------------------------------------------------------------- 1 | // compression must remove me 2 | var rf02=${value.rf02}; 3 | -------------------------------------------------------------------------------- /src/it/demo01/src/main/resources-redirect/file_rr01.js: -------------------------------------------------------------------------------- 1 | // compression must remove me 2 | var rr01="rr01"; 3 | -------------------------------------------------------------------------------- /src/it/demo01/src/main/resources-redirect/file_rr02.js: -------------------------------------------------------------------------------- 1 | // compression must remove me 2 | var rr02="rr02"; 3 | -------------------------------------------------------------------------------- /src/it/demo01/src/main/resources/file_r01.js: -------------------------------------------------------------------------------- 1 | // compression must remove me 2 | var r01="r01"; 3 | -------------------------------------------------------------------------------- /src/it/demo01/src/main/resources/file_r02.js: -------------------------------------------------------------------------------- 1 | // compression must remove me 2 | var r02="r02"; 3 | -------------------------------------------------------------------------------- /src/it/demo01/src/main/webapp/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | Archetype Created Web Application 7 | 8 | -------------------------------------------------------------------------------- /src/it/demo01/src/main/webapp/index.jsp: -------------------------------------------------------------------------------- 1 | 2 | 3 |

Hello World!

4 | 5 | 6 | -------------------------------------------------------------------------------- /src/it/demo01/src/main/webapp/static/highlighter.js: -------------------------------------------------------------------------------- 1 | // Highlighter script By Ilija Studen - http://ilija.biz/ 2 | // Modified from Woofoo forms 3 | 4 | /*--------------------------------------------------------------------------*/ 5 | 6 | //http://www.robertnyman.com/2005/11/07/the-ultimate-getelementsbyclassname/ 7 | function getElementsByClassName(oElm, strTagName, strClassName){ 8 | var arrElements = (strTagName == "*" && oElm.all)? oElm.all : oElm.getElementsByTagName(strTagName); 9 | var arrReturnElements = new Array(); 10 | strClassName = strClassName.replace(/\-/g, "\\-"); 11 | var oRegExp = new RegExp("(^|\\s)" + strClassName + "(\\s|$)"); 12 | var oElement; 13 | for(var i=0; i input{ 95 | } 96 | 97 | .inlineLabels .selectInput{ 98 | float:left; 99 | /* user prefs */ 100 | width:69%; 101 | border:2px solid #dfdfdf; 102 | } 103 | 104 | .inlineLabels textarea{ 105 | float:left; 106 | width:68%; 107 | /* user prefs */ 108 | border:2px solid #dfdfdf; 109 | height:12em; 110 | } 111 | 112 | .inlineLabels .formHint{ 113 | clear:both; 114 | /* user prefs */ 115 | color:#999; 116 | margin:.5em 0 0 30%; padding:3px 0; 117 | font-size:80%; 118 | } 119 | 120 | /* inlineLabels esthetics */ 121 | .inlineLabels .formHint strong{ 122 | padding:0 0 0 14px; 123 | background:url(img/icon_alert.png) 0 0 no-repeat; 124 | display:inline-block; 125 | } 126 | 127 | 128 | /* ########################################################################## */ 129 | 130 | /* Styles for form controls where labels are above the input elements */ 131 | /* Set the class to the parent to .blockLabels */ 132 | .blockLabels .ctrlHolder{ 133 | } 134 | 135 | .blockLabels label, 136 | .blockLabels .label{ 137 | display:block; 138 | float:none; 139 | margin:.3em 0; padding:0; 140 | line-height:100%; 141 | width:60%; 142 | /* user prefs */ 143 | font-weight:bold; 144 | width:auto; 145 | } 146 | .blockLabels .label{ 147 | float:left; 148 | margin-right:3em; 149 | } 150 | 151 | .blockLabels .textInput{ 152 | float:left; 153 | width:60%; 154 | /* user prefs */ 155 | border:2px solid #dfdfdf; 156 | } 157 | 158 | .blockLabels .selectInput{ 159 | float:left; 160 | width:60%; 161 | /* user prefs */ 162 | border:2px solid #dfdfdf; 163 | 164 | } 165 | 166 | .blockLabels textarea{ 167 | display:block; 168 | float:left; 169 | width:60%; 170 | /* user prefs */ 171 | border:2px solid #dfdfdf; 172 | height:12em; 173 | } 174 | 175 | .blockLabels .formHint{ 176 | float:right; 177 | margin:0; 178 | width:38%; 179 | clear:none; 180 | /* user prefs */ 181 | color:#999; 182 | font-size:80%; 183 | font-style:italic; 184 | } 185 | 186 | /* blockLabels esthetics */ 187 | .blockLabels .ctrlHolder{ 188 | border:1px solid #dfdfdf; border-width:1px 0; 189 | margin-top:-1px; 190 | } 191 | 192 | .blockLabels .focused{ 193 | padding:7px 4px; 194 | } 195 | 196 | /* ########################################################################## */ 197 | 198 | /* Focus pseudoclasses */ 199 | .ctrlHolder .textInput:focus{ 200 | border-color:#DFD77D; 201 | } 202 | div.focused .textInput:focus{ 203 | } 204 | div.focused .formHint{ 205 | color:#000; 206 | } 207 | 208 | /* Required asterisk styling, use if needed */ 209 | label em, 210 | .label em{ 211 | display:block; 212 | position:absolute; left:28%; 213 | font-style:normal; 214 | font-weight:bold; 215 | } 216 | .blockLabels label em, 217 | .blockLabels .label em{ 218 | position:static; 219 | display:inline; 220 | } 221 | 222 | /* Messages */ 223 | .uniForm #errorMsg{ 224 | background:#ffdfdf url(img/uf_error.png); 225 | border:1px solid #df7d7d; border-width:1px 0; 226 | margin:0 0 1em 0; padding:1em; 227 | } 228 | .uniForm .error, 229 | .uniForm .blockLabels.ctrlHolder.error{ 230 | background:#ffdfdf url(img/uf_error.png); 231 | border:1px solid #df7d7d; border-width:1px 0; 232 | position:relative; 233 | } 234 | .uniForm #errorMsg dt, 235 | .uniForm #errorMsg h3{ 236 | margin:0 0 .5em 0; 237 | font-size:110%; 238 | line-height:100%; 239 | font-weight:bold; 240 | color:#000; 241 | padding:2px 0 2px 18px; 242 | background:url(img/icon-error.png) 0 0 no-repeat; 243 | } 244 | .uniForm #errorMsg dd{ 245 | margin:0; padding:0; 246 | } 247 | .uniForm #errorMsg ol{ 248 | margin:0; padding:0; 249 | } 250 | .uniForm #errorMsg ol li{ 251 | margin:0; padding:2px; 252 | list-style-position:inside; 253 | border-bottom:1px dotted #df7d7d; 254 | position:relative; 255 | } 256 | .uniForm .errorField{ 257 | margin:0 0 3px 0; 258 | } 259 | .uniForm .inlineLabels .errorField{ 260 | margin-left:30%; 261 | } 262 | .uniForm .errorField strong{ 263 | background:#FFE2E2; 264 | padding:1px 3px 3px 3px; 265 | } 266 | .ctrlHolder.error input, 267 | .ctrlHolder.error input:focus{ 268 | border-color:#DF7D7D; 269 | } 270 | .ctrlHolder.error.focused{ 271 | padding:7px 4px; 272 | } 273 | -------------------------------------------------------------------------------- /src/it/demo01/src/main/webapp/static/uni-form.jquery.js: -------------------------------------------------------------------------------- 1 | jQuery.fn.uniform = function(settings) { 2 | settings = jQuery.extend({ 3 | valid_class : 'valid', 4 | invalid_class : 'invalid', 5 | focused_class : 'focused', 6 | holder_class : 'ctrlHolder', 7 | field_selector : 'input, select, textarea' 8 | }, settings); 9 | 10 | return this.each(function() { 11 | var form = jQuery(this); 12 | 13 | // Focus specific control holder 14 | var focusControlHolder = function(element) { 15 | var parent = element.parent(); 16 | 17 | while(typeof(parent) == 'object') { 18 | if(parent) { 19 | if(parent[0] && (parent[0].className.indexOf(settings.holder_class) >= 0)) { 20 | parent.addClass(settings.focused_class); 21 | return; 22 | } // if 23 | } // if 24 | parent = jQuery(parent.parent()); 25 | } // while 26 | }; 27 | 28 | // Select form fields and attach them higlighter functionality 29 | form.find(settings.field_selector).focus(function() { 30 | form.find('.' + settings.focused_class).removeClass(settings.focused_class); 31 | focusControlHolder(jQuery(this)); 32 | }).blur(function() { 33 | form.find('.' + settings.focused_class).removeClass(settings.focused_class); 34 | }); 35 | }); 36 | }; 37 | 38 | // Auto set on page load... 39 | $(document).ready(function() { 40 | jQuery('form.uniForm').uniform(); 41 | }); -------------------------------------------------------------------------------- /src/it/demo01/src/main/webapp/static/zero.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidB/yuicompressor-maven-plugin/175bbbdde555f6e6eb4419f352818849da4f8665/src/it/demo01/src/main/webapp/static/zero.js -------------------------------------------------------------------------------- /src/it/demo01/src/test/java/ResourcesTest.java: -------------------------------------------------------------------------------- 1 | package net_alchim31_maven_yuicompressor; 2 | 3 | import java.io.File; 4 | 5 | import junit.framework.TestCase; 6 | 7 | import org.apache.commons.io.FileUtils; 8 | 9 | public class ResourcesTest extends TestCase { 10 | 11 | private File outputDir_ = new File("target/classes"); 12 | 13 | public void testSimpleResources() throws Exception { 14 | File r01 = new File(outputDir_, "file_r01.js"); 15 | assertExists(r01); 16 | assertNoComments(r01); 17 | 18 | File r02 = new File(outputDir_, "file_r02.js"); 19 | assertExists(r02); 20 | assertNoComments(r02); 21 | } 22 | 23 | public void testResourcesWithFilter() throws Exception { 24 | File r01 = new File(outputDir_, "file_rf01.js"); 25 | assertExists(r01); 26 | assertNoComments(r01); 27 | assertNoFilteringValue(r01); 28 | 29 | File r02 = new File(outputDir_, "file_rf02.js"); 30 | assertExists(r02); 31 | assertNoComments(r02); 32 | assertNoFilteringValue(r02); 33 | } 34 | 35 | public void testResourcesWithTargetPath() throws Exception { 36 | File r01 = new File(outputDir_, "redirect/file_rr01.js"); 37 | assertExists(r01); 38 | assertNotExists(new File(outputDir_, "file_rr01.js")); 39 | assertNoComments(r01); 40 | 41 | File r02 = new File(outputDir_, "redirect/file_rr02.js"); 42 | assertExists(r02); 43 | assertNotExists(new File(outputDir_, "file_rr02.js")); 44 | assertNoComments(r02); 45 | } 46 | 47 | private void assertExists(File file) throws Exception { 48 | assertTrue(file.getName() + " not found", file.exists()); 49 | } 50 | 51 | private void assertNotExists(File file) throws Exception { 52 | assertFalse(file.getName() + " found", file.exists()); 53 | } 54 | 55 | private void assertNoComments(File file) throws Exception { 56 | String content = FileUtils.readFileToString(file); 57 | //System.out.println(file + ": "+ content); 58 | assertTrue("comments found (=> not compressed)", content.indexOf("//") < 0); 59 | assertTrue("comments found (=> not compressed)", content.indexOf("/*") < 0); 60 | } 61 | 62 | private void assertNoFilteringValue(File file) throws Exception { 63 | String content = FileUtils.readFileToString(file); 64 | assertTrue("property to filter found", content.indexOf("${") < 0); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/it/demo01/validate.groovy: -------------------------------------------------------------------------------- 1 | try { 2 | 3 | //TODO 4 | 5 | return true 6 | 7 | } catch(Throwable e) { 8 | e.printStackTrace() 9 | return false 10 | } -------------------------------------------------------------------------------- /src/it/issue19/invoker.properties: -------------------------------------------------------------------------------- 1 | invoker.goals=process-resources -------------------------------------------------------------------------------- /src/it/issue19/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | it.sandbox 7 | issu19 8 | 1.0-SNAPSHOT 9 | 10 | rf01 11 | rf02 12 | 13 | 14 | 15 | src/main/filters/dev.properties 16 | 17 | 18 | 19 | src/main/resources 20 | true 21 | 22 | webapp.properties 23 | 24 | 25 | 26 | 27 | 28 | @project.groupId@ 29 | yuicompressor-maven-plugin 30 | @project.version@ 31 | 32 | true 33 | false 34 | 35 | 36 | 37 | compress-js-css 38 | process-resources 39 | 40 | compress 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /src/it/issue19/src/main/filters/dev.properties: -------------------------------------------------------------------------------- 1 | prop.fake=fake -------------------------------------------------------------------------------- /src/it/issue19/src/main/resources/file_r01.js: -------------------------------------------------------------------------------- 1 | // compression must remove me 2 | var r01="r01"; 3 | -------------------------------------------------------------------------------- /src/it/issue19/src/main/resources/file_r02.js: -------------------------------------------------------------------------------- 1 | // compression must remove me 2 | var r02="r02"; 3 | -------------------------------------------------------------------------------- /src/it/issue19/src/main/resources/webapp.properties: -------------------------------------------------------------------------------- 1 | # a property file that should not be compressed,... 2 | # see https://github.com/davidB/yuicompressor-maven-plugin/issues/19 3 | 4 | prop.fake=${prop.fake} 5 | prop.rf01=${value.rf01} -------------------------------------------------------------------------------- /src/it/issue19/validate.groovy: -------------------------------------------------------------------------------- 1 | try { 2 | 3 | targetLg = new File(basedir, "target/classes/webapp.properties").size() 4 | assert targetLg > 0 : "webapp.properties empty (check that compression didn't run over it (=> remove content))" 5 | 6 | return true 7 | 8 | } catch(Throwable e) { 9 | e.printStackTrace() 10 | return false 11 | } -------------------------------------------------------------------------------- /src/main/java/net_alchim31_maven_yuicompressor/Aggregation.java: -------------------------------------------------------------------------------- 1 | package net_alchim31_maven_yuicompressor; 2 | 3 | import org.codehaus.plexus.util.DirectoryScanner; 4 | import org.codehaus.plexus.util.IOUtil; 5 | import org.sonatype.plexus.build.incremental.BuildContext; 6 | 7 | import java.io.File; 8 | import java.io.FileInputStream; 9 | import java.io.OutputStream; 10 | import java.util.*; 11 | 12 | public class Aggregation { 13 | public File inputDir; 14 | public File output; 15 | public String[] includes; 16 | public String[] excludes; 17 | public boolean removeIncluded = false; 18 | public boolean insertNewLine = false; 19 | public boolean insertFileHeader = false; 20 | public boolean fixLastSemicolon = false; 21 | public boolean autoExcludeWildcards = false; 22 | 23 | public List run(Collection previouslyIncludedFiles, BuildContext buildContext) throws Exception { 24 | return this.run(previouslyIncludedFiles, buildContext, null); 25 | } 26 | 27 | public List run(Collection previouslyIncludedFiles, BuildContext buildContext, Set incrementalFiles) throws Exception { 28 | defineInputDir(); 29 | 30 | List files; 31 | if (autoExcludeWildcards) { 32 | files = getIncludedFiles(previouslyIncludedFiles, buildContext, incrementalFiles); 33 | } else { 34 | files = getIncludedFiles(null, buildContext, incrementalFiles); 35 | } 36 | 37 | if (files.size() != 0) { 38 | output = output.getCanonicalFile(); 39 | output.getParentFile().mkdirs(); 40 | OutputStream out = buildContext.newFileOutputStream(output); 41 | try { 42 | for (File file : files) { 43 | if (file.getCanonicalPath().equals(output.getCanonicalPath())) { 44 | continue; 45 | } 46 | FileInputStream in = new FileInputStream(file); 47 | try { 48 | if (insertFileHeader) { 49 | out.write(createFileHeader(file).getBytes()); 50 | } 51 | IOUtil.copy(in, out); 52 | if (fixLastSemicolon) { 53 | out.write(';'); 54 | } 55 | if (insertNewLine) { 56 | out.write('\n'); 57 | } 58 | } finally { 59 | IOUtil.close(in); 60 | in = null; 61 | } 62 | if (removeIncluded) { 63 | file.delete(); 64 | buildContext.refresh(file); 65 | } 66 | } 67 | } finally { 68 | IOUtil.close(out); 69 | out = null; 70 | } 71 | } 72 | return files; 73 | } 74 | 75 | private String createFileHeader(File file) { 76 | StringBuilder header = new StringBuilder(); 77 | header.append("/*"); 78 | header.append(file.getName()); 79 | header.append("*/"); 80 | 81 | if (insertNewLine) { 82 | header.append('\n'); 83 | } 84 | 85 | return header.toString(); 86 | } 87 | 88 | private void defineInputDir() throws Exception { 89 | if (inputDir == null) { 90 | inputDir = output.getParentFile(); 91 | } 92 | inputDir = inputDir.getCanonicalFile(); 93 | if (!inputDir.isDirectory()) { 94 | throw new IllegalStateException("input directory not found: " + inputDir); 95 | } 96 | } 97 | 98 | private List getIncludedFiles(Collection previouslyIncludedFiles, BuildContext buildContext, Set incrementalFiles) throws Exception { 99 | List filesToAggregate = new ArrayList<>(); 100 | if (includes != null) { 101 | for (String include : includes) { 102 | addInto(include, filesToAggregate, previouslyIncludedFiles); 103 | } 104 | } 105 | 106 | //If build is incremental with no delta, then don't include for aggregation 107 | if (buildContext.isIncremental()) { 108 | 109 | if (incrementalFiles != null) { 110 | boolean aggregateMustBeUpdated = false; 111 | for (File file : filesToAggregate) { 112 | if (incrementalFiles.contains(file.getAbsolutePath())) { 113 | aggregateMustBeUpdated = true; 114 | break; 115 | } 116 | } 117 | 118 | if (aggregateMustBeUpdated) { 119 | return filesToAggregate; 120 | } 121 | } 122 | return new ArrayList(); 123 | } else { 124 | return filesToAggregate; 125 | } 126 | 127 | } 128 | 129 | private void addInto(String include, List includedFiles, Collection previouslyIncludedFiles) throws Exception { 130 | if (include.indexOf('*') > -1) { 131 | DirectoryScanner scanner = newScanner(); 132 | scanner.setIncludes(new String[]{include}); 133 | scanner.scan(); 134 | String[] rpaths = scanner.getIncludedFiles(); 135 | Arrays.sort(rpaths); 136 | for (String rpath : rpaths) { 137 | File file = new File(scanner.getBasedir(), rpath); 138 | if (!includedFiles.contains(file) && (previouslyIncludedFiles == null || !previouslyIncludedFiles.contains(file))) { 139 | includedFiles.add(file); 140 | } 141 | } 142 | } else { 143 | File file = new File(include); 144 | if (!file.isAbsolute()) { 145 | file = new File(inputDir, include); 146 | } 147 | if (!includedFiles.contains(file)) { 148 | includedFiles.add(file); 149 | } 150 | } 151 | } 152 | 153 | private DirectoryScanner newScanner() throws Exception { 154 | DirectoryScanner scanner = new DirectoryScanner(); 155 | scanner.setBasedir(inputDir); 156 | if ((excludes != null) && (excludes.length != 0)) { 157 | scanner.setExcludes(excludes); 158 | } 159 | scanner.addDefaultExcludes(); 160 | return scanner; 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /src/main/java/net_alchim31_maven_yuicompressor/BasicRhinoShell.java: -------------------------------------------------------------------------------- 1 | /* ***** BEGIN LICENSE BLOCK ***** 2 | * Version: MPL 1.1/GPL 2.0 3 | * 4 | * The contents of this file are subject to the Mozilla Public License Version 5 | * 1.1 (the "License"); you may not use this file except in compliance with 6 | * the License. You may obtain a copy of the License at 7 | * http://www.mozilla.org/MPL/ 8 | * 9 | * Software distributed under the License is distributed on an "AS IS" basis, 10 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 11 | * for the specific language governing rights and limitations under the 12 | * License. 13 | * 14 | * The Original Code is Rhino code, released 15 | * May 6, 1998. 16 | * 17 | * The Initial Developer of the Original Code is 18 | * Netscape Communications Corporation. 19 | * Portions created by the Initial Developer are Copyright (C) 1997-1999 20 | * the Initial Developer. All Rights Reserved. 21 | * 22 | * Contributor(s): 23 | * 24 | * Alternatively, the contents of this file may be used under the terms of 25 | * the GNU General Public License Version 2 or later (the "GPL"), in which 26 | * case the provisions of the GPL are applicable instead of those above. If 27 | * you wish to allow use of your version of this file only under the terms of 28 | * the GPL and not to allow others to use your version of this file under the 29 | * MPL, indicate your decision by deleting the provisions above and replacing 30 | * them with the notice and other provisions required by the GPL. If you do 31 | * not delete the provisions above, a recipient may use your version of this 32 | * file under either the MPL or the GPL. 33 | * 34 | * ***** END LICENSE BLOCK ***** */ 35 | 36 | package net_alchim31_maven_yuicompressor; 37 | 38 | import org.codehaus.plexus.util.IOUtil; 39 | import org.mozilla.javascript.*; 40 | 41 | import java.io.*; 42 | 43 | /** 44 | * The BasicRhinoShell program. 45 | *

46 | * Can execute scripts interactively or in batch mode at the command line. An 47 | * example of controlling the JavaScript engine. 48 | * 49 | * @author Norris Boyd 50 | * @based http://lxr.mozilla.org/mozilla/source/js/rhino/examples/BasicRhinoShell.java 51 | * (2007-08-30) 52 | */ 53 | @SuppressWarnings("serial") 54 | public class BasicRhinoShell extends ScriptableObject { 55 | 56 | @Override 57 | public String getClassName() { 58 | return "global"; 59 | } 60 | 61 | /** 62 | * Main entry point. 63 | *

64 | * Process arguments as would a normal Java program. Also create a new 65 | * Context and associate it with the current thread. Then set up the 66 | * execution environment and begin to execute scripts. 67 | */ 68 | public static void exec(String[] args, ErrorReporter reporter) { 69 | // Associate a new Context with this thread 70 | Context cx = Context.enter(); 71 | cx.setErrorReporter(reporter); 72 | try { 73 | // Initialize the standard objects (Object, Function, etc.) 74 | // This must be done before scripts can be executed. 75 | BasicRhinoShell BasicRhinoShell = new BasicRhinoShell(); 76 | cx.initStandardObjects(BasicRhinoShell); 77 | 78 | // Define some global functions particular to the BasicRhinoShell. 79 | // Note 80 | // that these functions are not part of ECMA. 81 | String[] names = {"print", "quit", "version", "load", "help", "readFile", "warn"}; 82 | BasicRhinoShell.defineFunctionProperties(names, BasicRhinoShell.class, ScriptableObject.DONTENUM); 83 | 84 | args = processOptions(cx, args); 85 | 86 | // Set up "arguments" in the global scope to contain the command 87 | // line arguments after the name of the script to execute 88 | Object[] array; 89 | if (args.length == 0) { 90 | array = new Object[0]; 91 | } else { 92 | int length = args.length - 1; 93 | array = new Object[length]; 94 | System.arraycopy(args, 1, array, 0, length); 95 | } 96 | Scriptable argsObj = cx.newArray(BasicRhinoShell, array); 97 | BasicRhinoShell.defineProperty("arguments", argsObj, ScriptableObject.DONTENUM); 98 | 99 | BasicRhinoShell.processSource(cx, args.length == 0 ? null : args[0]); 100 | } finally { 101 | Context.exit(); 102 | } 103 | } 104 | 105 | /** 106 | * Parse arguments. 107 | */ 108 | public static String[] processOptions(Context cx, String[] args) { 109 | for (int i = 0; i < args.length; i++) { 110 | String arg = args[i]; 111 | if (!arg.startsWith("-")) { 112 | String[] result = new String[args.length - i]; 113 | for (int j = i; j < args.length; j++) { 114 | result[j - i] = args[j]; 115 | } 116 | return result; 117 | } 118 | if (arg.equals("-version")) { 119 | if (++i == args.length) { 120 | usage(arg); 121 | } 122 | double d = Context.toNumber(args[i]); 123 | if (d != d) { 124 | usage(arg); 125 | } 126 | cx.setLanguageVersion((int) d); 127 | continue; 128 | } 129 | usage(arg); 130 | } 131 | return new String[0]; 132 | } 133 | 134 | /** 135 | * Print a usage message. 136 | */ 137 | private static void usage(String s) { 138 | p("Didn't understand \"" + s + "\"."); 139 | p("Valid arguments are:"); 140 | p("-version 100|110|120|130|140|150|160|170"); 141 | System.exit(1); 142 | } 143 | 144 | /** 145 | * Print a help message. 146 | *

147 | * This method is defined as a JavaScript function. 148 | */ 149 | public void help() { 150 | p(""); 151 | p("Command Description"); 152 | p("======= ==========="); 153 | p("help() Display usage and help messages. "); 154 | p("defineClass(className) Define an extension using the Java class"); 155 | p(" named with the string argument. "); 156 | p(" Uses ScriptableObject.defineClass(). "); 157 | p("load(['foo.js', ...]) Load JavaScript source files named by "); 158 | p(" string arguments. "); 159 | p("loadClass(className) Load a class named by a string argument."); 160 | p(" The class must be a script compiled to a"); 161 | p(" class file. "); 162 | p("print([expr ...]) Evaluate and print expressions. "); 163 | p("quit() Quit the BasicRhinoShell. "); 164 | p("version([number]) Get or set the JavaScript version number."); 165 | p(""); 166 | } 167 | 168 | /** 169 | * Print the string values of its arguments. 170 | *

171 | * This method is defined as a JavaScript function. Note that its arguments 172 | * are of the "varargs" form, which allows it to handle an arbitrary number 173 | * of arguments supplied to the JavaScript function. 174 | */ 175 | public static void print(Context cx, Scriptable thisObj, Object[] args, Function funObj) { 176 | for (int i = 0; i < args.length; i++) { 177 | if (i > 0) { 178 | System.out.print(" "); 179 | } 180 | 181 | // Convert the arbitrary JavaScript value into a string form. 182 | String s = Context.toString(args[i]); 183 | 184 | System.out.print(s); 185 | } 186 | System.out.println(); 187 | } 188 | 189 | /** 190 | * Quit the BasicRhinoShell. 191 | *

192 | * This only affects the interactive mode. 193 | *

194 | * This method is defined as a JavaScript function. 195 | */ 196 | public void quit() { 197 | quitting = true; 198 | } 199 | 200 | public static void warn(Context cx, Scriptable thisObj, Object[] args, Function funObj) { 201 | String message = Context.toString(args[0]); 202 | int line = (int) Context.toNumber(args[1]); 203 | String source = Context.toString(args[2]); 204 | int column = (int) Context.toNumber(args[3]); 205 | cx.getErrorReporter().warning(message, null, line, source, column); 206 | } 207 | 208 | /** 209 | * This method is defined as a JavaScript function. 210 | */ 211 | public String readFile(String path) { 212 | try { 213 | return IOUtil.toString(new FileInputStream(path)); 214 | } catch (RuntimeException exc) { 215 | throw exc; 216 | } catch (Exception exc) { 217 | throw new RuntimeException("wrap: " + exc.getMessage(), exc); 218 | } 219 | } 220 | 221 | /** 222 | * Get and set the language version. 223 | *

224 | * This method is defined as a JavaScript function. 225 | */ 226 | public static double version(Context cx, Scriptable thisObj, Object[] args, Function funObj) { 227 | double result = cx.getLanguageVersion(); 228 | if (args.length > 0) { 229 | double d = Context.toNumber(args[0]); 230 | cx.setLanguageVersion((int) d); 231 | } 232 | return result; 233 | } 234 | 235 | /** 236 | * Load and execute a set of JavaScript source files. 237 | *

238 | * This method is defined as a JavaScript function. 239 | */ 240 | public static void load(Context cx, Scriptable thisObj, Object[] args, Function funObj) { 241 | BasicRhinoShell BasicRhinoShell = (BasicRhinoShell) getTopLevelScope(thisObj); 242 | for (Object element : args) { 243 | BasicRhinoShell.processSource(cx, Context.toString(element)); 244 | } 245 | } 246 | 247 | /** 248 | * Evaluate JavaScript source. 249 | * 250 | * @param cx the current context 251 | * @param filename the name of the file to compile, or null for interactive 252 | * mode. 253 | */ 254 | private void processSource(Context cx, String filename) { 255 | if (filename == null) { 256 | BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); 257 | String sourceName = ""; 258 | int lineno = 1; 259 | boolean hitEOF = false; 260 | do { 261 | int startline = lineno; 262 | System.err.print("js> "); 263 | System.err.flush(); 264 | try { 265 | String source = ""; 266 | // Collect lines of source to compile. 267 | while (true) { 268 | String newline; 269 | newline = in.readLine(); 270 | if (newline == null) { 271 | hitEOF = true; 272 | break; 273 | } 274 | source = source + newline + "\n"; 275 | lineno++; 276 | // Continue collecting as long as more lines 277 | // are needed to complete the current 278 | // statement. stringIsCompilableUnit is also 279 | // true if the source statement will result in 280 | // any error other than one that might be 281 | // resolved by appending more source. 282 | if (cx.stringIsCompilableUnit(source)) { 283 | break; 284 | } 285 | } 286 | Object result = cx.evaluateString(this, source, sourceName, startline, null); 287 | if (result != Context.getUndefinedValue()) { 288 | System.err.println(Context.toString(result)); 289 | } 290 | } catch (WrappedException we) { 291 | // Some form of exception was caught by JavaScript and 292 | // propagated up. 293 | System.err.println(we.getWrappedException().toString()); 294 | we.printStackTrace(); 295 | } catch (EvaluatorException ee) { 296 | // Some form of JavaScript error. 297 | System.err.println("js: " + ee.getMessage()); 298 | } catch (JavaScriptException jse) { 299 | // Some form of JavaScript error. 300 | System.err.println("js: " + jse.getMessage()); 301 | } catch (IOException ioe) { 302 | System.err.println(ioe.toString()); 303 | } 304 | if (quitting) { 305 | // The user executed the quit() function. 306 | break; 307 | } 308 | } while (!hitEOF); 309 | System.err.println(); 310 | } else { 311 | FileReader in = null; 312 | try { 313 | in = new FileReader(filename); 314 | } catch (FileNotFoundException ex) { 315 | Context.reportError("Couldn't open file \"" + filename + "\"."); 316 | return; 317 | } 318 | 319 | try { 320 | // Here we evalute the entire contents of the file as 321 | // a script. Text is printed only if the print() function 322 | // is called. 323 | cx.evaluateReader(this, in, filename, 1, null); 324 | } catch (WrappedException we) { 325 | System.err.println(we.getWrappedException().toString()); 326 | we.printStackTrace(); 327 | } catch (EvaluatorException ee) { 328 | System.err.println("js: " + ee.getMessage()); 329 | } catch (JavaScriptException jse) { 330 | System.err.println("js: " + jse.getMessage()); 331 | } catch (IOException ioe) { 332 | System.err.println(ioe.toString()); 333 | } finally { 334 | try { 335 | in.close(); 336 | } catch (IOException ioe) { 337 | System.err.println(ioe.toString()); 338 | } 339 | } 340 | } 341 | } 342 | 343 | private static void p(String s) { 344 | System.out.println(s); 345 | } 346 | 347 | private boolean quitting; 348 | } 349 | -------------------------------------------------------------------------------- /src/main/java/net_alchim31_maven_yuicompressor/ErrorReporter4Mojo.java: -------------------------------------------------------------------------------- 1 | package net_alchim31_maven_yuicompressor; 2 | 3 | import org.apache.maven.plugin.logging.Log; 4 | import org.mozilla.javascript.ErrorReporter; 5 | import org.mozilla.javascript.EvaluatorException; 6 | import org.sonatype.plexus.build.incremental.BuildContext; 7 | 8 | import java.io.File; 9 | 10 | public class ErrorReporter4Mojo implements ErrorReporter { 11 | 12 | private String defaultFilename_; 13 | private boolean acceptWarn_; 14 | private Log log_; 15 | private int warningCnt_; 16 | private int errorCnt_; 17 | private BuildContext buildContext_; 18 | private File sourceFile_; 19 | 20 | public ErrorReporter4Mojo(Log log, boolean jswarn, BuildContext buildContext) { 21 | log_ = log; 22 | acceptWarn_ = jswarn; 23 | buildContext_ = buildContext; 24 | } 25 | 26 | public void setDefaultFileName(String v) { 27 | if (v.length() == 0) { 28 | v = null; 29 | } 30 | defaultFilename_ = v; 31 | } 32 | 33 | public int getErrorCnt() { 34 | return errorCnt_; 35 | } 36 | 37 | public int getWarningCnt() { 38 | return warningCnt_; 39 | } 40 | 41 | public void error(String message, String sourceName, int line, String lineSource, int lineOffset) { 42 | String fullMessage = newMessage(message, sourceName, line, lineSource, lineOffset); 43 | buildContext_.addMessage(sourceFile_, line, lineOffset, message, BuildContext.SEVERITY_ERROR, null); 44 | log_.error(fullMessage); 45 | errorCnt_++; 46 | } 47 | 48 | public EvaluatorException runtimeError(String message, String sourceName, int line, String lineSource, int lineOffset) { 49 | error(message, sourceName, line, lineSource, lineOffset); 50 | throw new EvaluatorException(message, sourceName, line, lineSource, lineOffset); 51 | } 52 | 53 | public void warning(String message, String sourceName, int line, String lineSource, int lineOffset) { 54 | if (acceptWarn_) { 55 | String fullMessage = newMessage(message, sourceName, line, lineSource, lineOffset); 56 | buildContext_.addMessage(sourceFile_, line, lineOffset, message, BuildContext.SEVERITY_WARNING, null); 57 | log_.warn(fullMessage); 58 | warningCnt_++; 59 | } 60 | } 61 | 62 | private String newMessage(String message, String sourceName, int line, String lineSource, int lineOffset) { 63 | StringBuilder back = new StringBuilder(); 64 | if ((sourceName == null) || (sourceName.length() == 0)) { 65 | sourceName = defaultFilename_; 66 | } 67 | if (sourceName != null) { 68 | back.append(sourceName) 69 | .append(":line ") 70 | .append(line) 71 | .append(":column ") 72 | .append(lineOffset) 73 | .append(':') 74 | ; 75 | } 76 | if ((message != null) && (message.length() != 0)) { 77 | back.append(message); 78 | } else { 79 | back.append("unknown error"); 80 | } 81 | if ((lineSource != null) && (lineSource.length() != 0)) { 82 | back.append("\n\t") 83 | .append(lineSource) 84 | ; 85 | } 86 | return back.toString(); 87 | } 88 | 89 | public void setFile(File file) { 90 | sourceFile_ = file; 91 | } 92 | 93 | } 94 | -------------------------------------------------------------------------------- /src/main/java/net_alchim31_maven_yuicompressor/JSLintChecker.java: -------------------------------------------------------------------------------- 1 | package net_alchim31_maven_yuicompressor; 2 | 3 | import org.codehaus.plexus.util.IOUtil; 4 | import org.mozilla.javascript.ErrorReporter; 5 | 6 | import java.io.File; 7 | import java.io.FileOutputStream; 8 | import java.io.InputStream; 9 | 10 | //TODO: use MojoErrorReporter 11 | class JSLintChecker { 12 | private String jslintPath_; 13 | 14 | public JSLintChecker() throws Exception { 15 | FileOutputStream out = null; 16 | InputStream in = null; 17 | try { 18 | File jslint = File.createTempFile("jslint", ".js"); 19 | jslint.deleteOnExit(); 20 | in = getClass().getResourceAsStream("/jslint.js"); 21 | out = new FileOutputStream(jslint); 22 | IOUtil.copy(in, out); 23 | jslintPath_ = jslint.getAbsolutePath(); 24 | } finally { 25 | IOUtil.close(in); 26 | IOUtil.close(out); 27 | } 28 | } 29 | 30 | public void check(File jsFile, ErrorReporter reporter) { 31 | String[] args = new String[2]; 32 | args[0] = jslintPath_; 33 | args[1] = jsFile.getAbsolutePath(); 34 | BasicRhinoShell.exec(args, reporter); 35 | //if (Main.exec(args) != 0) { 36 | // reporter.warning("warnings during checking of :" + jsFile.getAbsolutePath(), null, -1, null, -1); 37 | //} 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/net_alchim31_maven_yuicompressor/JSLintMojo.java: -------------------------------------------------------------------------------- 1 | package net_alchim31_maven_yuicompressor; 2 | 3 | 4 | /** 5 | * Check JS files with jslint. 6 | * 7 | * @author David Bernard 8 | * @goal jslint 9 | * @phase process-resources 10 | * @created 2007-08-29 11 | * @threadSafe 12 | */ 13 | // @SuppressWarnings("unchecked") 14 | public class JSLintMojo extends MojoSupport { 15 | private JSLintChecker jslint_; 16 | 17 | @Override 18 | protected String[] getDefaultIncludes() throws Exception { 19 | return new String[]{"**/**.js"}; 20 | } 21 | 22 | @Override 23 | public void beforeProcess() throws Exception { 24 | jslint_ = new JSLintChecker(); 25 | } 26 | 27 | @Override 28 | public void afterProcess() throws Exception { 29 | } 30 | 31 | @Override 32 | protected void processFile(SourceFile src) throws Exception { 33 | getLog().info("check file :" + src.toFile()); 34 | jslint_.check(src.toFile(), jsErrorReporter_); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/net_alchim31_maven_yuicompressor/MojoSupport.java: -------------------------------------------------------------------------------- 1 | package net_alchim31_maven_yuicompressor; 2 | 3 | import org.apache.maven.model.Resource; 4 | import org.apache.maven.plugin.AbstractMojo; 5 | import org.apache.maven.plugin.MojoExecutionException; 6 | import org.apache.maven.plugin.MojoFailureException; 7 | import org.apache.maven.project.MavenProject; 8 | import org.codehaus.plexus.util.DirectoryScanner; 9 | import org.codehaus.plexus.util.Scanner; 10 | import org.sonatype.plexus.build.incremental.BuildContext; 11 | 12 | import java.io.File; 13 | import java.util.List; 14 | 15 | /** 16 | * Common class for mojos. 17 | * 18 | * @author David Bernard 19 | * @created 2007-08-29 20 | */ 21 | // @SuppressWarnings("unchecked") 22 | public abstract class MojoSupport extends AbstractMojo { 23 | private static final String[] EMPTY_STRING_ARRAY = {}; 24 | 25 | /** 26 | * Javascript source directory. (result will be put to outputDirectory). 27 | * This allow project with "src/main/js" structure. 28 | * 29 | * @parameter expression="${project.build.sourceDirectory}/../js" 30 | */ 31 | private File sourceDirectory; 32 | 33 | /** 34 | * Single directory for extra files to include in the WAR. 35 | * 36 | * @parameter expression="${basedir}/src/main/webapp" 37 | */ 38 | private File warSourceDirectory; 39 | 40 | /** 41 | * The directory where the webapp is built. 42 | * 43 | * @parameter expression="${project.build.directory}/${project.build.finalName}" 44 | */ 45 | private File webappDirectory; 46 | 47 | /** 48 | * The output directory into which to copy the resources. 49 | * 50 | * @parameter property="project.build.outputDirectory" 51 | */ 52 | private File outputDirectory; 53 | 54 | /** 55 | * The list of resources we want to transfer. 56 | * 57 | * @parameter property="project.resources" 58 | */ 59 | private List resources; 60 | 61 | /** 62 | * list of additional excludes 63 | * 64 | * @parameter 65 | */ 66 | private List excludes; 67 | 68 | /** 69 | * Use processed resources if available 70 | * 71 | * @parameter default-value="false" 72 | */ 73 | private boolean useProcessedResources; 74 | 75 | /** 76 | * list of additional includes 77 | * 78 | * @parameter 79 | */ 80 | private List includes; 81 | 82 | /** 83 | * Excludes files from webapp directory 84 | * 85 | * @parameter 86 | */ 87 | private boolean excludeWarSourceDirectory = false; 88 | 89 | /** 90 | * Excludes files from resources directories. 91 | * 92 | * @parameter default-value="false" 93 | */ 94 | private boolean excludeResources = false; 95 | 96 | /** 97 | * @parameter property="project" 98 | * @readonly 99 | * @required 100 | */ 101 | protected MavenProject project; 102 | 103 | /** 104 | * [js only] Display possible errors in the code 105 | * 106 | * @parameter property="maven.yuicompressor.jswarn" default-value="true" 107 | */ 108 | protected boolean jswarn; 109 | 110 | /** 111 | * Whether to skip execution. 112 | * 113 | * @parameter property="maven.yuicompressor.skip" default-value="false" 114 | */ 115 | private boolean skip; 116 | 117 | /** 118 | * define if plugin must stop/fail on warnings. 119 | * 120 | * @parameter property="maven.yuicompressor.failOnWarning" default-value="false" 121 | */ 122 | protected boolean failOnWarning; 123 | 124 | /** 125 | * @component 126 | */ 127 | protected BuildContext buildContext; 128 | 129 | protected ErrorReporter4Mojo jsErrorReporter_; 130 | 131 | public void execute() throws MojoExecutionException, MojoFailureException { 132 | try { 133 | if (skip) { 134 | getLog().debug("run of yuicompressor-maven-plugin skipped"); 135 | return; 136 | } 137 | if (failOnWarning) { 138 | jswarn = true; 139 | } 140 | jsErrorReporter_ = new ErrorReporter4Mojo(getLog(), jswarn, buildContext); 141 | beforeProcess(); 142 | processDir(sourceDirectory, outputDirectory, null, useProcessedResources); 143 | if (!excludeResources) { 144 | for (Resource resource : resources) { 145 | File destRoot = outputDirectory; 146 | if (resource.getTargetPath() != null) { 147 | destRoot = new File(outputDirectory, resource.getTargetPath()); 148 | } 149 | processDir(new File(resource.getDirectory()), destRoot, resource.getExcludes(), useProcessedResources); 150 | } 151 | } 152 | if (!excludeWarSourceDirectory) { 153 | processDir(warSourceDirectory, webappDirectory, null, useProcessedResources); 154 | } 155 | afterProcess(); 156 | getLog().info(String.format("nb warnings: %d, nb errors: %d", jsErrorReporter_.getWarningCnt(), jsErrorReporter_.getErrorCnt())); 157 | if (failOnWarning && (jsErrorReporter_.getWarningCnt() > 0)) { 158 | throw new MojoFailureException("warnings on " + this.getClass().getSimpleName() + "=> failure ! (see log)"); 159 | } 160 | } catch (RuntimeException exc) { 161 | throw exc; 162 | } catch (MojoFailureException exc) { 163 | throw exc; 164 | } catch (MojoExecutionException exc) { 165 | throw exc; 166 | } catch (Exception exc) { 167 | throw new MojoExecutionException("wrap: " + exc.getMessage(), exc); 168 | } 169 | } 170 | 171 | protected abstract String[] getDefaultIncludes() throws Exception; 172 | 173 | protected abstract void beforeProcess() throws Exception; 174 | 175 | protected abstract void afterProcess() throws Exception; 176 | 177 | /** 178 | * Force to use defaultIncludes (ignore srcIncludes) to avoid processing resources/includes from other type than *.css or *.js 179 | * 180 | * see https://github.com/davidB/yuicompressor-maven-plugin/issues/19 181 | */ 182 | private void processDir(File srcRoot, File destRoot, List srcExcludes, boolean destAsSource) throws Exception { 183 | if (srcRoot == null) { 184 | return; 185 | } 186 | if (!srcRoot.exists()) { 187 | buildContext.addMessage(srcRoot, 0, 0, "Directory " + srcRoot.getPath() + " does not exists", BuildContext.SEVERITY_WARNING, null); 188 | getLog().info("Directory " + srcRoot.getPath() + " does not exists"); 189 | return; 190 | } 191 | if (destRoot == null) { 192 | throw new MojoFailureException("destination directory for " + srcRoot + " is null"); 193 | } 194 | Scanner scanner; 195 | if (!buildContext.isIncremental()) { 196 | DirectoryScanner dScanner = new DirectoryScanner(); 197 | dScanner.setBasedir(srcRoot); 198 | scanner = dScanner; 199 | } else { 200 | scanner = buildContext.newScanner(srcRoot); 201 | } 202 | 203 | if (includes == null) { 204 | scanner.setIncludes(getDefaultIncludes()); 205 | } else { 206 | scanner.setIncludes(includes.toArray(new String[0])); 207 | } 208 | 209 | if ((srcExcludes != null) && !srcExcludes.isEmpty()) { 210 | scanner.setExcludes(srcExcludes.toArray(EMPTY_STRING_ARRAY)); 211 | } 212 | if ((excludes != null) && !excludes.isEmpty()) { 213 | scanner.setExcludes(excludes.toArray(EMPTY_STRING_ARRAY)); 214 | } 215 | scanner.addDefaultExcludes(); 216 | 217 | scanner.scan(); 218 | 219 | String[] includedFiles = scanner.getIncludedFiles(); 220 | if (includedFiles == null || includedFiles.length == 0) { 221 | if (buildContext.isIncremental()) { 222 | getLog().info("No files have changed, so skipping the processing"); 223 | } else { 224 | getLog().info("No files to be processed"); 225 | } 226 | return; 227 | } 228 | for (String name : includedFiles) { 229 | SourceFile src = new SourceFile(srcRoot, destRoot, name, destAsSource); 230 | jsErrorReporter_.setDefaultFileName("..." + src.toFile().getAbsolutePath().substring(src.toFile().getAbsolutePath().lastIndexOf('/') + 1)); 231 | jsErrorReporter_.setFile(src.toFile()); 232 | processFile(src); 233 | } 234 | } 235 | 236 | protected abstract void processFile(SourceFile src) throws Exception; 237 | } 238 | -------------------------------------------------------------------------------- /src/main/java/net_alchim31_maven_yuicompressor/SourceFile.java: -------------------------------------------------------------------------------- 1 | package net_alchim31_maven_yuicompressor; 2 | 3 | import java.io.File; 4 | 5 | public class SourceFile { 6 | 7 | private File srcRoot_; 8 | private File destRoot_; 9 | private boolean destAsSource_; 10 | private String rpath_; 11 | private String extension_; 12 | 13 | public SourceFile(File srcRoot, File destRoot, String name, boolean destAsSource) throws Exception { 14 | srcRoot_ = srcRoot; 15 | destRoot_ = destRoot; 16 | destAsSource_ = destAsSource; 17 | rpath_ = name; 18 | int sep = rpath_.lastIndexOf('.'); 19 | if (sep > 0) { 20 | extension_ = rpath_.substring(sep); 21 | rpath_ = rpath_.substring(0, sep); 22 | } else { 23 | extension_ = ""; 24 | } 25 | } 26 | 27 | public File toFile() { 28 | String frpath = rpath_ + extension_; 29 | if (destAsSource_) { 30 | File defaultDest = new File(destRoot_, frpath); 31 | if (defaultDest.exists() && defaultDest.canRead()) { 32 | return defaultDest; 33 | } 34 | } 35 | return new File(srcRoot_, frpath); 36 | } 37 | 38 | public File toDestFile(String suffix) { 39 | return new File(destRoot_, rpath_ + suffix + extension_); 40 | } 41 | 42 | public String getExtension() { 43 | return extension_; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/net_alchim31_maven_yuicompressor/YuiCompressorMojo.java: -------------------------------------------------------------------------------- 1 | package net_alchim31_maven_yuicompressor; 2 | 3 | import com.yahoo.platform.yui.compressor.CssCompressor; 4 | import com.yahoo.platform.yui.compressor.JavaScriptCompressor; 5 | import org.apache.maven.plugin.MojoExecutionException; 6 | import org.codehaus.plexus.util.FileUtils; 7 | import org.codehaus.plexus.util.IOUtil; 8 | 9 | import java.io.*; 10 | import java.util.Collection; 11 | import java.util.HashSet; 12 | import java.util.Set; 13 | import java.util.zip.GZIPOutputStream; 14 | 15 | /** 16 | * Apply compression on JS and CSS (using YUI Compressor). 17 | * 18 | * @author David Bernard 19 | * @goal compress 20 | * @phase process-resources 21 | * @created 2007-08-28 22 | * @threadSafe 23 | */ 24 | // @SuppressWarnings("unchecked") 25 | public class YuiCompressorMojo extends MojoSupport { 26 | 27 | /** 28 | * Read the input file using "encoding". 29 | * 30 | * @parameter property="file.encoding" default-value="UTF-8" 31 | */ 32 | private String encoding; 33 | 34 | /** 35 | * The output filename suffix. 36 | * 37 | * @parameter property="maven.yuicompressor.suffix" default-value="-min" 38 | */ 39 | private String suffix; 40 | 41 | /** 42 | * If no "suffix" must be add to output filename (maven's configuration manage empty suffix like default). 43 | * 44 | * @parameter property="maven.yuicompressor.nosuffix" default-value="false" 45 | */ 46 | private boolean nosuffix; 47 | 48 | /** 49 | * Insert line breaks in output after the specified column number. 50 | * 51 | * @parameter property="maven.yuicompressor.linebreakpos" default-value="-1" 52 | */ 53 | private int linebreakpos; 54 | 55 | /** 56 | * [js only] No compression 57 | * 58 | * @parameter property="maven.yuicompressor.nocompress" default-value="false" 59 | */ 60 | private boolean nocompress; 61 | 62 | /** 63 | * [js only] Minify only, do not obfuscate. 64 | * 65 | * @parameter property="maven.yuicompressor.nomunge" default-value="false" 66 | */ 67 | private boolean nomunge; 68 | 69 | /** 70 | * [js only] Preserve unnecessary semicolons. 71 | * 72 | * @parameter property="maven.yuicompressor.preserveAllSemiColons" default-value="false" 73 | */ 74 | private boolean preserveAllSemiColons; 75 | 76 | /** 77 | * [js only] disable all micro optimizations. 78 | * 79 | * @parameter property="maven.yuicompressor.disableOptimizations" default-value="false" 80 | */ 81 | private boolean disableOptimizations; 82 | 83 | /** 84 | * force the compression of every files, 85 | * else if compressed file already exists and is younger than source file, nothing is done. 86 | * 87 | * @parameter property="maven.yuicompressor.force" default-value="false" 88 | */ 89 | private boolean force; 90 | 91 | /** 92 | * a list of aggregation/concatenation to do after processing, 93 | * for example to create big js files that contain several small js files. 94 | * Aggregation could be done on any type of file (js, css, ...). 95 | * 96 | * @parameter 97 | */ 98 | private Aggregation[] aggregations; 99 | 100 | /** 101 | * request to create a gzipped version of the yuicompressed/aggregation files. 102 | * 103 | * @parameter property="maven.yuicompressor.gzip" default-value="false" 104 | */ 105 | private boolean gzip; 106 | 107 | /** 108 | * gzip level 109 | * 110 | * @parameter property="maven.yuicompressor.level" default-value="9" 111 | */ 112 | private int level; 113 | 114 | /** 115 | * show statistics (compression ratio). 116 | * 117 | * @parameter property="maven.yuicompressor.statistics" default-value="true" 118 | */ 119 | private boolean statistics; 120 | 121 | /** 122 | * aggregate files before minify 123 | * 124 | * @parameter property="maven.yuicompressor.preProcessAggregates" default-value="false" 125 | */ 126 | private boolean preProcessAggregates; 127 | 128 | /** 129 | * use the input file as output when the compressed file is larger than the original 130 | * 131 | * @parameter property="maven.yuicompressor.useSmallestFile" default-value="true" 132 | */ 133 | private boolean useSmallestFile; 134 | 135 | private long inSizeTotal_; 136 | private long outSizeTotal_; 137 | 138 | /** 139 | * Keep track of updated files for aggregation on incremental builds 140 | */ 141 | private Set incrementalFiles = null; 142 | 143 | @Override 144 | protected String[] getDefaultIncludes() throws Exception { 145 | return new String[]{"**/*.css", "**/*.js"}; 146 | } 147 | 148 | @Override 149 | public void beforeProcess() throws Exception { 150 | if (nosuffix) { 151 | suffix = ""; 152 | } 153 | 154 | if (preProcessAggregates) aggregate(); 155 | } 156 | 157 | @Override 158 | protected void afterProcess() throws Exception { 159 | if (statistics && (inSizeTotal_ > 0)) { 160 | getLog().info(String.format("total input (%db) -> output (%db)[%d%%]", inSizeTotal_, outSizeTotal_, ((outSizeTotal_ * 100) / inSizeTotal_))); 161 | } 162 | 163 | if (!preProcessAggregates) aggregate(); 164 | } 165 | 166 | private void aggregate() throws Exception { 167 | if (aggregations != null) { 168 | Set previouslyIncludedFiles = new HashSet(); 169 | for (Aggregation aggregation : aggregations) { 170 | getLog().info("generate aggregation : " + aggregation.output); 171 | Collection aggregatedFiles = aggregation.run(previouslyIncludedFiles, buildContext, incrementalFiles); 172 | previouslyIncludedFiles.addAll(aggregatedFiles); 173 | 174 | File gzipped = gzipIfRequested(aggregation.output); 175 | if (statistics) { 176 | if (gzipped != null) { 177 | getLog().info(String.format("%s (%db) -> %s (%db)[%d%%]", aggregation.output.getName(), aggregation.output.length(), gzipped.getName(), gzipped.length(), ratioOfSize(aggregation.output, gzipped))); 178 | } else if (aggregation.output.exists()) { 179 | getLog().info(String.format("%s (%db)", aggregation.output.getName(), aggregation.output.length())); 180 | } else { 181 | getLog().warn(String.format("%s not created", aggregation.output.getName())); 182 | } 183 | } 184 | } 185 | } 186 | } 187 | 188 | @Override 189 | protected void processFile(SourceFile src) throws Exception { 190 | File inFile = src.toFile(); 191 | getLog().debug("on incremental build only compress if input file has Delta"); 192 | if (buildContext.isIncremental()) { 193 | if (!buildContext.hasDelta(inFile)) { 194 | if (getLog().isInfoEnabled()) { 195 | getLog().info("nothing to do, " + inFile + " has no Delta"); 196 | } 197 | return; 198 | } 199 | if (incrementalFiles == null) { 200 | incrementalFiles = new HashSet(); 201 | } 202 | } 203 | 204 | if (getLog().isDebugEnabled()) { 205 | getLog().debug("compress file :" + src.toFile() + " to " + src.toDestFile(suffix)); 206 | } 207 | 208 | File outFile = src.toDestFile(suffix); 209 | if (isMinifiedFile(inFile)) { 210 | return; 211 | } 212 | if (minifiedFileExistsInSource(inFile, outFile)) { 213 | getLog().info("compressed file " + outFile.getAbsolutePath() + " already exists in the source directory: " + inFile.getAbsolutePath()); 214 | return; 215 | } 216 | getLog().debug("only compress if input file is younger than existing output file"); 217 | if (!force && outFile.exists() && (outFile.lastModified() > inFile.lastModified())) { 218 | if (getLog().isInfoEnabled()) { 219 | getLog().info("nothing to do, " + outFile + " is younger than original, use 'force' option or clean your target"); 220 | } 221 | return; 222 | } 223 | InputStreamReader in = null; 224 | OutputStreamWriter out = null; 225 | File outFileTmp = new File(outFile.getAbsolutePath() + ".tmp"); 226 | FileUtils.forceDelete(outFileTmp); 227 | try { 228 | in = new InputStreamReader(new FileInputStream(inFile), encoding); 229 | if (!outFile.getParentFile().exists() && !outFile.getParentFile().mkdirs()) { 230 | throw new MojoExecutionException("Cannot create resource output directory: " + outFile.getParentFile()); 231 | } 232 | getLog().debug("use a temporary outputfile (in case in == out)"); 233 | 234 | getLog().debug("start compression"); 235 | /* outFileTmp will be deleted create with FileOutputStream */ 236 | out = new OutputStreamWriter(new FileOutputStream(outFileTmp), encoding); 237 | if (nocompress) { 238 | getLog().info("No compression is enabled"); 239 | IOUtil.copy(in, out); 240 | } else if (".js".equalsIgnoreCase(src.getExtension())) { 241 | JavaScriptCompressor compressor = new JavaScriptCompressor(in, jsErrorReporter_); 242 | compressor.compress(out, linebreakpos, !nomunge, jswarn, preserveAllSemiColons, disableOptimizations); 243 | } else if (".css".equalsIgnoreCase(src.getExtension())) { 244 | compressCss(in, out); 245 | } 246 | getLog().debug("end compression"); 247 | } finally { 248 | IOUtil.close(in); 249 | IOUtil.close(out); 250 | } 251 | 252 | boolean outputIgnored = useSmallestFile && inFile.length() < outFile.length(); 253 | if (outputIgnored) { 254 | FileUtils.forceDelete(outFileTmp); 255 | FileUtils.copyFile(inFile, outFile); 256 | getLog().debug("output greater than input, using original instead"); 257 | } else { 258 | FileUtils.forceDelete(outFile); 259 | FileUtils.rename(outFileTmp, outFile); 260 | buildContext.refresh(outFile); 261 | } 262 | 263 | if (buildContext.isIncremental()) { 264 | incrementalFiles.add(outFile.getAbsolutePath()); 265 | } 266 | 267 | File gzipped = gzipIfRequested(outFile); 268 | if (statistics) { 269 | inSizeTotal_ += inFile.length(); 270 | outSizeTotal_ += outFile.length(); 271 | 272 | String fileStatistics; 273 | if (outputIgnored) { 274 | fileStatistics = String.format("%s (%db) -> %s (%db)[compressed output discarded (exceeded input size)]", inFile.getName(), inFile.length(), outFile.getName(), outFile.length()); 275 | } else { 276 | fileStatistics = String.format("%s (%db) -> %s (%db)[%d%%]", inFile.getName(), inFile.length(), outFile.getName(), outFile.length(), ratioOfSize(inFile, outFile)); 277 | } 278 | 279 | if (gzipped != null) { 280 | fileStatistics = fileStatistics + String.format(" -> %s (%db)[%d%%]", gzipped.getName(), gzipped.length(), ratioOfSize(inFile, gzipped)); 281 | } 282 | getLog().info(fileStatistics); 283 | } 284 | } 285 | 286 | private void compressCss(InputStreamReader in, OutputStreamWriter out) 287 | throws IOException { 288 | try { 289 | CssCompressor compressor = new CssCompressor(in); 290 | compressor.compress(out, linebreakpos); 291 | } catch (IllegalArgumentException e) { 292 | throw new IllegalArgumentException( 293 | "Unexpected characters found in CSS file. Ensure that the CSS file does not contain '$', and try again", e); 294 | } 295 | } 296 | 297 | protected File gzipIfRequested(File file) throws Exception { 298 | if (!gzip || (file == null) || (!file.exists())) { 299 | return null; 300 | } 301 | if (".gz".equalsIgnoreCase(FileUtils.getExtension(file.getName()))) { 302 | return null; 303 | } 304 | File gzipped = new File(file.getAbsolutePath() + ".gz"); 305 | getLog().debug(String.format("create gzip version : %s", gzipped.getName())); 306 | GZIPOutputStream out = null; 307 | FileInputStream in = null; 308 | try { 309 | out = new GZIPOutputStream(buildContext.newFileOutputStream(gzipped)) { 310 | { 311 | def.setLevel(level); 312 | } 313 | }; 314 | in = new FileInputStream(file); 315 | IOUtil.copy(in, out); 316 | } finally { 317 | IOUtil.close(in); 318 | IOUtil.close(out); 319 | } 320 | return gzipped; 321 | } 322 | 323 | protected long ratioOfSize(File file100, File fileX) throws Exception { 324 | long v100 = Math.max(file100.length(), 1); 325 | long vX = Math.max(fileX.length(), 1); 326 | return (vX * 100) / v100; 327 | } 328 | 329 | private boolean isMinifiedFile(File inFile) { 330 | String filename = inFile.getName().toLowerCase(); 331 | return filename.endsWith(suffix + ".js") || filename.endsWith(suffix + ".css"); 332 | } 333 | 334 | private static boolean minifiedFileExistsInSource(File source, File dest) throws InterruptedException { 335 | String parent = source.getParent(); 336 | String destFilename = dest.getName(); 337 | File file = new File(parent + File.separator + destFilename); 338 | return file.exists(); 339 | } 340 | } 341 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/m2e/lifecycle-mapping-metadata.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | compress 8 | jslint 9 | 10 | 11 | 12 | 13 | false 14 | true 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/site/default-site.vm: -------------------------------------------------------------------------------- 1 | 2 | 3 | #macro ( link $href $name $target $img $position $alt $border $width $height ) 4 | #set ( $linkTitle = ' title="' + $name + '"' ) 5 | #if( $target ) 6 | #set ( $linkTarget = ' target="' + $target + '"' ) 7 | #else 8 | #set ( $linkTarget = "" ) 9 | #end 10 | #if ( ( $href.toLowerCase().startsWith("http") || $href.toLowerCase().startsWith("https") ) ) 11 | #set ( $linkClass = ' class="externalLink"' ) 12 | #else 13 | #set ( $linkClass = "" ) 14 | #end 15 | #if ( $img ) 16 | #if ( $position == "left" ) 17 | #image($img $alt $border $width $height)$name 18 | #else 19 | $name #image($img $alt $border $width $height) 20 | #end 21 | #else 22 | $name 23 | #end 24 | #end 25 | ## 26 | #macro ( image $img $alt $border $width $height ) 27 | #if( $img ) 28 | #if ( ! ( $img.toLowerCase().startsWith("http") || $img.toLowerCase().startsWith("https") ) ) 29 | #set ( $imgSrc = $PathTool.calculateLink( $img, $relativePath ) ) 30 | #set ( $imgSrc = $imgSrc.replaceAll( '\\', '/' ) ) 31 | #set ( $imgSrc = ' src="' + $imgSrc + '"' ) 32 | #else 33 | #set ( $imgSrc = ' src="' + $img + '"' ) 34 | #end 35 | #if( $alt ) 36 | #set ( $imgAlt = ' alt="' + $alt + '"' ) 37 | #else 38 | #set ( $imgAlt = ' alt=""' ) 39 | #end 40 | #if( $border ) 41 | #set ( $imgBorder = ' border="' + $border + '"' ) 42 | #else 43 | #set ( $imgBorder = "" ) 44 | #end 45 | #if( $width ) 46 | #set ( $imgWidth = ' width="' + $width + '"' ) 47 | #else 48 | #set ( $imgWidth = "" ) 49 | #end 50 | #if( $height ) 51 | #set ( $imgHeight = ' height="' + $height + '"' ) 52 | #else 53 | #set ( $imgHeight = "" ) 54 | #end 55 | 56 | #end 57 | #end 58 | #macro ( banner $banner $id ) 59 | #if ( $banner ) 60 | #if( $banner.href ) 61 | 62 | #else 63 |

86 | #end 87 | #end 88 | #end 89 | ## 90 | #macro ( links $links ) 91 | #set ( $counter = 0 ) 92 | #foreach( $item in $links ) 93 | #set ( $counter = $counter + 1 ) 94 | #set ( $currentItemHref = $PathTool.calculateLink( $item.href, $relativePath ) ) 95 | #set ( $currentItemHref = $currentItemHref.replaceAll( '\\', '/' ) ) 96 | #link( $currentItemHref $item.name $item.target $item.img $item.position $item.alt $item.border $item.width $item.height ) 97 | #if ( $links.size() > $counter ) 98 | | 99 | #end 100 | #end 101 | #end 102 | ## 103 | #macro ( breadcrumbs $breadcrumbs ) 104 | #set ( $counter = 0 ) 105 | #foreach( $item in $breadcrumbs ) 106 | #set ( $counter = $counter + 1 ) 107 | #set ( $currentItemHref = $PathTool.calculateLink( $item.href, $relativePath ) ) 108 | #set ( $currentItemHref = $currentItemHref.replaceAll( '\\', '/' ) ) 109 | ## 110 | #if ( $currentItemHref == $alignedFileName || $currentItemHref == "" ) 111 | $item.name 112 | #else 113 | #link( $currentItemHref $item.name $item.target $item.img $item.position $item.alt $item.border $item.width $item.height ) 114 | #end 115 | #if ( $breadcrumbs.size() > $counter ) 116 | > 117 | #end 118 | #end 119 | #end 120 | ## 121 | #macro ( displayTree $display $item ) 122 | #if ( $item && $item.items && $item.items.size() > 0 ) 123 | #foreach( $subitem in $item.items ) 124 | #set ( $subitemHref = $PathTool.calculateLink( $subitem.href, $relativePath ) ) 125 | #set ( $subitemHref = $subitemHref.replaceAll( '\\', '/' ) ) 126 | #if ( $alignedFileName == $subitemHref ) 127 | #set ( $display = true ) 128 | #end 129 | ## 130 | #displayTree( $display $subitem ) 131 | #end 132 | #end 133 | #end 134 | ## 135 | #macro ( menuItem $item ) 136 | #set ( $collapse = "none" ) 137 | #set ( $currentItemHref = $PathTool.calculateLink( $item.href, $relativePath ) ) 138 | #set ( $currentItemHref = $currentItemHref.replaceAll( '\\', '/' ) ) 139 | ## 140 | #if ( $item && $item.items && $item.items.size() > 0 ) 141 | #if ( $item.collapse == false ) 142 | #set ( $collapse = "expanded" ) 143 | #else 144 | ## By default collapsed 145 | #set ( $collapse = "collapsed" ) 146 | #end 147 | ## 148 | #set ( $display = false ) 149 | #displayTree( $display $item ) 150 | ## 151 | #if ( $alignedFileName == $currentItemHref || $display ) 152 | #set ( $collapse = "expanded" ) 153 | #end 154 | #end 155 |
  • 156 | #if ( $item.img ) 157 | #if ( $item.position == "left" ) 158 | #if ( $alignedFileName == $currentItemHref ) 159 | #image($item.img $item.alt $item.border $item.width $item.height) $item.name 160 | #else 161 | #link($currentItemHref $item.name $item.target $item.img $item.position $item.alt $item.border $item.width $item.height) 162 | #end 163 | #else 164 | #if ( $alignedFileName == $currentItemHref ) 165 | $item.name #image($item.img $item.alt $item.border $item.width $item.height) 166 | #else 167 | #link($currentItemHref $item.name $item.target $item.img $item.position $item.alt $item.border $item.width $item.height) 168 | #end 169 | #end 170 | #else 171 | #if ( $alignedFileName == $currentItemHref ) 172 | $item.name 173 | #else 174 | #link( $currentItemHref $item.name $item.target $item.img $item.position $item.alt $item.border $item.width $item.height ) 175 | #end 176 | #end 177 | #if ( $item && $item.items && $item.items.size() > 0 ) 178 | #if ( $collapse == "expanded" ) 179 |
      180 | #foreach( $subitem in $item.items ) 181 | #menuItem( $subitem ) 182 | #end 183 |
    184 | #end 185 | #end 186 |
  • 187 | #end 188 | ## 189 | #macro ( mainMenu $menus ) 190 | #foreach( $menu in $menus ) 191 | #if ( $menu.name ) 192 | #if ( $menu.img ) 193 | #if( $menu.position ) 194 | #set ( $position = $menu.position ) 195 | #else 196 | #set ( $position = "left" ) 197 | #end 198 | ## 199 | #if ( ! ( $menu.img.toLowerCase().startsWith("http") || $menu.img.toLowerCase().startsWith("https") ) ) 200 | #set ( $src = $PathTool.calculateLink( $menu.img, $relativePath ) ) 201 | #set ( $src = $src.replaceAll( '\\', '/' ) ) 202 | #set ( $src = ' src="' + $src + '"' ) 203 | #else 204 | #set ( $src = ' src="' + $menu.img + '"' ) 205 | #end 206 | ## 207 | #if( $menu.alt ) 208 | #set ( $alt = ' alt="' + $menu.alt + '"' ) 209 | #else 210 | #set ( $alt = ' alt="' + $menu.name + '"' ) 211 | #end 212 | ## 213 | #if( $menu.border ) 214 | #set ( $border = ' border="' + $menu.border + '"' ) 215 | #else 216 | #set ( $border = ' border="0"' ) 217 | #end 218 | ## 219 | #if( $menu.width ) 220 | #set ( $width = ' width="' + $menu.width + '"' ) 221 | #else 222 | #set ( $width = "" ) 223 | #end 224 | #if( $menu.height ) 225 | #set ( $height = ' height="' + $menu.height + '"' ) 226 | #else 227 | #set ( $height = "" ) 228 | #end 229 | ## 230 | #set ( $img = '" ) 231 | ## 232 | #if ( $position == "left" ) 233 |
    $img $menu.name
    234 | #else 235 |
    $menu.name $img
    236 | #end 237 | #else 238 |
    $menu.name
    239 | #end 240 | #end 241 | #if ( $menu.items && $menu.items.size() > 0 ) 242 |
      243 | #foreach( $item in $menu.items ) 244 | #menuItem( $item ) 245 | #end 246 |
    247 | #end 248 | #end 249 | #end 250 | ## 251 | #macro ( copyright ) 252 | #if ( $project ) 253 | #if ( ${project.organization} && ${project.organization.name} ) 254 | #set ( $period = "" ) 255 | #else 256 | #set ( $period = "." ) 257 | #end 258 | ## 259 | #set ( $currentYear = ${currentDate.year} + 1900 ) 260 | ## 261 | #if ( ${project.inceptionYear} && ( ${project.inceptionYear} != ${currentYear.toString()} ) ) 262 | ${project.inceptionYear}-${currentYear}${period} 263 | #else 264 | ${currentYear}${period} 265 | #end 266 | ## 267 | #if ( ${project.organization} ) 268 | #if ( ${project.organization.name} && ${project.organization.url} ) 269 | ${project.organization.name}. 270 | #elseif ( ${project.organization.name} ) 271 | ${project.organization.name}. 272 | #end 273 | #end 274 | #end 275 | #end 276 | ## 277 | #macro ( publishDate $position $publishDate $version ) 278 | #if ( $publishDate && $publishDate.format ) 279 | #set ( $format = $publishDate.format ) 280 | #else 281 | #set ( $format = "yyyy-MM-dd" ) 282 | #end 283 | ## 284 | $dateFormat.applyPattern( $format ) 285 | ## 286 | #set ( $dateToday = $dateFormat.format( $currentDate ) ) 287 | ## 288 | #if ( $publishDate && $publishDate.position ) 289 | #set ( $datePosition = $publishDate.position ) 290 | #else 291 | #set ( $datePosition = "left" ) 292 | #end 293 | ## 294 | #if ( $version ) 295 | #if ( $version.position ) 296 | #set ( $versionPosition = $version.position ) 297 | #else 298 | #set ( $versionPosition = "left" ) 299 | #end 300 | #else 301 | #set ( $version = "" ) 302 | #set ( $versionPosition = "left" ) 303 | #end 304 | ## 305 | #set ( $breadcrumbs = $decoration.body.breadcrumbs ) 306 | #set ( $links = $decoration.body.links ) 307 | 308 | #if ( $datePosition.equalsIgnoreCase( "right" ) && $links && $links.size() > 0 ) 309 | #set ( $prefix = " |" ) 310 | #else 311 | #set ( $prefix = "" ) 312 | #end 313 | ## 314 | #if ( $datePosition.equalsIgnoreCase( $position ) ) 315 | #if ( ( $datePosition.equalsIgnoreCase( "right" ) ) || ( $datePosition.equalsIgnoreCase( "bottom" ) ) ) 316 | $prefix $i18n.getString( "site-renderer", $locale, "template.lastpublished" ): $dateToday 317 | #if ( $versionPosition.equalsIgnoreCase( $position ) ) 318 |  | $i18n.getString( "site-renderer", $locale, "template.version" ): ${project.version} 319 | #end 320 | #elseif ( ( $datePosition.equalsIgnoreCase( "navigation-bottom" ) ) || ( $datePosition.equalsIgnoreCase( "navigation-top" ) ) ) 321 |
    322 | $i18n.getString( "site-renderer", $locale, "template.lastpublished" ): $dateToday 323 | #if ( $versionPosition.equalsIgnoreCase( $position ) ) 324 |  | $i18n.getString( "site-renderer", $locale, "template.version" ): ${project.version} 325 | #end 326 |
    327 | #elseif ( $datePosition.equalsIgnoreCase("left") ) 328 |
    329 | $i18n.getString( "site-renderer", $locale, "template.lastpublished" ): $dateToday 330 | #if ( $versionPosition.equalsIgnoreCase( $position ) ) 331 |  | $i18n.getString( "site-renderer", $locale, "template.version" ): ${project.version} 332 | #end 333 | #if ( $breadcrumbs && $breadcrumbs.size() > 0 ) 334 | | #breadcrumbs( $breadcrumbs ) 335 | #end 336 |
    337 | #end 338 | #elseif ( $versionPosition.equalsIgnoreCase( $position ) ) 339 | #if ( ( $versionPosition.equalsIgnoreCase( "right" ) ) || ( $versionPosition.equalsIgnoreCase( "bottom" ) ) ) 340 | $prefix $i18n.getString( "site-renderer", $locale, "template.version" ): ${project.version} 341 | #elseif ( ( $versionPosition.equalsIgnoreCase( "navigation-bottom" ) ) || ( $versionPosition.equalsIgnoreCase( "navigation-top" ) ) ) 342 |
    343 | $i18n.getString( "site-renderer", $locale, "template.version" ): ${project.version} 344 |
    345 | #elseif ( $versionPosition.equalsIgnoreCase("left") ) 346 |
    347 | $i18n.getString( "site-renderer", $locale, "template.version" ): ${project.version} 348 | #if ( $breadcrumbs && $breadcrumbs.size() > 0 ) 349 | | #breadcrumbs( $breadcrumbs ) 350 | #end 351 |
    352 | #end 353 | #elseif ( $position.equalsIgnoreCase( "left" ) ) 354 | #if ( $breadcrumbs && $breadcrumbs.size() > 0 ) 355 |
    356 | #breadcrumbs( $breadcrumbs ) 357 |
    358 | #end 359 | #end 360 | #end 361 | ## 362 | #macro ( poweredByLogo $poweredBy ) 363 | #if( $poweredBy ) 364 | #foreach ($item in $poweredBy) 365 | #if( $item.href ) 366 | #set ( $href = $PathTool.calculateLink( $item.href, $relativePath ) ) 367 | #set ( $href = $href.replaceAll( '\\', '/' ) ) 368 | #else 369 | #set ( $href="http://maven.apache.org/" ) 370 | #end 371 | ## 372 | #if( $item.name ) 373 | #set ( $name = $item.name ) 374 | #else 375 | #set ( $name = $i18n.getString( "site-renderer", $locale, "template.builtby" ) ) 376 | #set ( $name = "${name} Maven" ) 377 | #end 378 | ## 379 | #if( $item.img ) 380 | #set ( $img = $item.img ) 381 | #else 382 | #set ( $img = "images/logos/maven-feather.png" ) 383 | #end 384 | ## 385 | #if ( ! ( $img.toLowerCase().startsWith("http") || $img.toLowerCase().startsWith("https") ) ) 386 | #set ( $img = $PathTool.calculateLink( $img, $relativePath ) ) 387 | #set ( $img = $src.replaceAll( '\\', '/' ) ) 388 | #end 389 | ## 390 | #if( $item.alt ) 391 | #set ( $alt = ' alt="' + $item.alt + '"' ) 392 | #else 393 | #set ( $alt = ' alt="' + $name + '"' ) 394 | #end 395 | ## 396 | #if( $item.border ) 397 | #set ( $border = ' border="' + $item.border + '"' ) 398 | #else 399 | #set ( $border = "" ) 400 | #end 401 | ## 402 | #if( $item.width ) 403 | #set ( $width = ' width="' + $item.width + '"' ) 404 | #else 405 | #set ( $width = "" ) 406 | #end 407 | #if( $item.height ) 408 | #set ( $height = ' height="' + $item.height + '"' ) 409 | #else 410 | #set ( $height = "" ) 411 | #end 412 | ## 413 | 414 | 415 | 416 | #end 417 | #if( $poweredBy.isEmpty() ) 418 | 419 | $i18n.getString( 420 | 421 | #end 422 | #else 423 | 424 | $i18n.getString( 425 | 426 | #end 427 | #end 428 | ## 429 | 430 | 431 | 432 | $title 433 | 438 | 439 | #foreach( $author in $authors ) 440 | 441 | #end 442 | #if ( $dateCreation ) 443 | 444 | #end 445 | #if ( $dateRevision ) 446 | 447 | #end 448 | #if ( $locale ) 449 | 450 | #end 451 | #if ( $decoration.body.head ) 452 | #foreach( $item in $decoration.body.head.getChildren() ) 453 | ## Workaround for DOXIA-150 due to a non-desired behaviour in p-u 454 | ## @see org.codehaus.plexus.util.xml.Xpp3Dom#toString() 455 | ## @see org.codehaus.plexus.util.xml.Xpp3Dom#toUnescapedString() 456 | #set ( $documentHeader = '' ) 457 | #if ( $item.name == "script" ) 458 | $StringUtils.replace( $item.toUnescapedString(), $documentHeader, "" ) 459 | #else 460 | $StringUtils.replace( $item.toString(), $documentHeader, "" ) 461 | #end 462 | #end 463 | #end 464 | $headContent 465 | 466 | 467 | 474 | 481 |
    482 | 488 |
    489 |
    490 |
    491 | $bodyContent 492 |
    493 |
    494 |
    495 |
    496 |
    497 | 503 | 504 | 505 | -------------------------------------------------------------------------------- /src/site/resources/css/maven-base.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0px; 3 | padding: 0px; 4 | } 5 | img { 6 | border:none; 7 | } 8 | table { 9 | padding:0px; 10 | width: 100%; 11 | margin-left: -2px; 12 | margin-right: -2px; 13 | } 14 | acronym { 15 | cursor: help; 16 | border-bottom: 1px dotted #feb; 17 | } 18 | table.bodyTable th, table.bodyTable td { 19 | padding: 2px 4px 2px 4px; 20 | vertical-align: top; 21 | } 22 | div.clear{ 23 | clear:both; 24 | visibility: hidden; 25 | } 26 | div.clear hr{ 27 | display: none; 28 | } 29 | #bannerLeft, #bannerRight { 30 | font-size: xx-large; 31 | font-weight: bold; 32 | } 33 | #bannerLeft img, #bannerRight img { 34 | margin: 0px; 35 | } 36 | .xleft, #bannerLeft img { 37 | float:left; 38 | } 39 | .xright, #bannerRight { 40 | float:right; 41 | } 42 | #banner { 43 | padding: 0px; 44 | } 45 | #banner img { 46 | border: none; 47 | } 48 | #breadcrumbs { 49 | padding: 3px 10px 3px 10px; 50 | } 51 | #leftColumn { 52 | width: 170px; 53 | float:left; 54 | overflow: auto; 55 | } 56 | #bodyColumn { 57 | margin-right: 1.5em; 58 | margin-left: 197px; 59 | } 60 | #legend { 61 | padding: 8px 0 8px 0; 62 | } 63 | #navcolumn { 64 | padding: 8px 4px 0 8px; 65 | } 66 | #navcolumn h5 { 67 | margin: 0; 68 | padding: 0; 69 | font-size: small; 70 | } 71 | #navcolumn ul { 72 | margin: 0; 73 | padding: 0; 74 | font-size: small; 75 | } 76 | #navcolumn li { 77 | list-style-type: none; 78 | background-image: none; 79 | background-repeat: no-repeat; 80 | background-position: 0 0.4em; 81 | padding-left: 16px; 82 | list-style-position: outside; 83 | line-height: 1.2em; 84 | font-size: smaller; 85 | } 86 | #navcolumn li.expanded { 87 | background-image: url(../images/expanded.gif); 88 | } 89 | #navcolumn li.collapsed { 90 | background-image: url(../images/collapsed.gif); 91 | } 92 | #poweredBy { 93 | text-align: center; 94 | } 95 | #navcolumn img { 96 | margin-top: 10px; 97 | margin-bottom: 3px; 98 | } 99 | #poweredBy img { 100 | display:block; 101 | margin: 20px 0 20px 17px; 102 | } 103 | #search img { 104 | margin: 0px; 105 | display: block; 106 | } 107 | #search #q, #search #btnG { 108 | border: 1px solid #999; 109 | margin-bottom:10px; 110 | } 111 | #search form { 112 | margin: 0px; 113 | } 114 | #lastPublished { 115 | font-size: x-small; 116 | } 117 | .navSection { 118 | margin-bottom: 2px; 119 | padding: 8px; 120 | } 121 | .navSectionHead { 122 | font-weight: bold; 123 | font-size: x-small; 124 | } 125 | .section { 126 | padding: 4px; 127 | } 128 | #footer { 129 | padding: 3px 10px 3px 10px; 130 | font-size: x-small; 131 | } 132 | #breadcrumbs { 133 | font-size: x-small; 134 | margin: 0pt; 135 | } 136 | .source { 137 | padding: 12px; 138 | margin: 1em 7px 1em 7px; 139 | } 140 | .source pre { 141 | margin: 0px; 142 | padding: 0px; 143 | } 144 | #navcolumn img.imageLink, .imageLink { 145 | padding-left: 0px; 146 | padding-bottom: 0px; 147 | padding-top: 0px; 148 | padding-right: 2px; 149 | border: 0px; 150 | margin: 0px; 151 | } 152 | -------------------------------------------------------------------------------- /src/site/resources/css/maven-theme.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding: 0px 0px 10px 0px; 3 | } 4 | body, td, select, input, li{ 5 | font-family: Verdana, Helvetica, Arial, sans-serif; 6 | font-size: 13px; 7 | } 8 | code{ 9 | font-family: Courier, monospace; 10 | font-size: 13px; 11 | } 12 | a { 13 | text-decoration: none; 14 | } 15 | a:link { 16 | color:#36a; 17 | } 18 | a:visited { 19 | color:#47a; 20 | } 21 | a:active, a:hover { 22 | color:#69c; 23 | } 24 | #legend li.externalLink { 25 | background: url(../images/external.png) left top no-repeat; 26 | padding-left: 18px; 27 | } 28 | a.externalLink, a.externalLink:link, a.externalLink:visited, a.externalLink:active, a.externalLink:hover { 29 | background: url(../images/external.png) right center no-repeat; 30 | padding-right: 18px; 31 | } 32 | #legend li.newWindow { 33 | background: url(../images/newwindow.png) left top no-repeat; 34 | padding-left: 18px; 35 | } 36 | a.newWindow, a.newWindow:link, a.newWindow:visited, a.newWindow:active, a.newWindow:hover { 37 | background: url(../images/newwindow.png) right center no-repeat; 38 | padding-right: 18px; 39 | } 40 | h2 { 41 | padding: 4px 4px 4px 6px; 42 | border: 1px solid #999; 43 | color: #900; 44 | background-color: #ddd; 45 | font-weight:900; 46 | font-size: x-large; 47 | } 48 | h3 { 49 | padding: 4px 4px 4px 6px; 50 | border: 1px solid #aaa; 51 | color: #900; 52 | background-color: #eee; 53 | font-weight: normal; 54 | font-size: large; 55 | } 56 | h4 { 57 | padding: 4px 4px 4px 6px; 58 | border: 1px solid #bbb; 59 | color: #900; 60 | background-color: #fff; 61 | font-weight: normal; 62 | font-size: large; 63 | } 64 | h5 { 65 | padding: 4px 4px 4px 6px; 66 | color: #900; 67 | font-size: normal; 68 | } 69 | p { 70 | line-height: 1.3em; 71 | font-size: small; 72 | } 73 | #breadcrumbs { 74 | border-top: 1px solid #aaa; 75 | border-bottom: 1px solid #aaa; 76 | background-color: #ccc; 77 | } 78 | #leftColumn { 79 | margin: 10px 0 0 5px; 80 | border: 1px solid #999; 81 | background-color: #eee; 82 | } 83 | #navcolumn h5 { 84 | font-size: smaller; 85 | border-bottom: 1px solid #aaaaaa; 86 | padding-top: 2px; 87 | color: #000; 88 | } 89 | 90 | table.bodyTable th { 91 | color: white; 92 | background-color: #bbb; 93 | text-align: left; 94 | font-weight: bold; 95 | } 96 | 97 | table.bodyTable th, table.bodyTable td { 98 | font-size: 1em; 99 | } 100 | 101 | table.bodyTable tr.a { 102 | background-color: #ddd; 103 | } 104 | 105 | table.bodyTable tr.b { 106 | background-color: #eee; 107 | } 108 | 109 | .source { 110 | border: 1px solid #999; 111 | } 112 | dl { 113 | padding: 4px 4px 4px 6px; 114 | border: 1px solid #aaa; 115 | background-color: #ffc; 116 | } 117 | dt { 118 | color: #900; 119 | } 120 | #organizationLogo img, #projectLogo img, #projectLogo span{ 121 | margin: 8px; 122 | } 123 | #banner { 124 | border-bottom: 1px solid #fff; 125 | } 126 | .errormark, .warningmark, .donemark, .infomark { 127 | background: url(../images/icon_error_sml.gif) no-repeat; 128 | } 129 | 130 | .warningmark { 131 | background-image: url(../images/icon_warning_sml.gif); 132 | } 133 | 134 | .donemark { 135 | background-image: url(../images/icon_success_sml.gif); 136 | } 137 | 138 | .infomark { 139 | background-image: url(../images/icon_info_sml.gif); 140 | } 141 | 142 | -------------------------------------------------------------------------------- /src/site/resources/css/print.css: -------------------------------------------------------------------------------- 1 | #banner, #footer, #leftcol, #breadcrumbs, .docs #toc, .docs .courtesylinks, #leftColumn, #navColumn { 2 | display: none !important; 3 | } 4 | #bodyColumn, body.docs div.docs { 5 | margin: 0 !important; 6 | border: none !important 7 | } 8 | -------------------------------------------------------------------------------- /src/site/resources/css/site.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: #fff; 3 | font-family: Verdana, Helvetica, Arial, sans-serif; 4 | margin-left: auto; 5 | margin-right: auto; 6 | background-repeat: repeat-y; 7 | font-size: 13px; 8 | padding: 0px; 9 | } 10 | 11 | table,table td,table th { 12 | border-radius: 4px; 13 | -moz-border-radius: 4px !important; 14 | } 15 | 16 | #leftColumn { 17 | width: 170px; 18 | float: left; 19 | } 20 | 21 | #bodyColumn { 22 | margin-right: 1.5em; 23 | margin-left: 197px; 24 | } 25 | 26 | td,select,input,li { 27 | font-family: Verdana, Helvetica, Arial, sans-serif; 28 | font-size: 12px; 29 | color: #333333; 30 | } 31 | 32 | code { 33 | font-size: 12px; 34 | } 35 | 36 | a { 37 | text-decoration: none; 38 | } 39 | 40 | a:link { 41 | color: #47a; 42 | } 43 | 44 | a:visited { 45 | color: #666666; 46 | } 47 | 48 | a:active,a:hover { 49 | color: #990000; 50 | } 51 | 52 | h2 { 53 | font-family: Arial, Helvetica, sans-serif; 54 | font-size: 28px; 55 | color: #666; 56 | background: none; 57 | font-weight: normal; 58 | padding-left: 0; 59 | border: none; 60 | border-bottom: 1px dotted #ccc; 61 | } 62 | 63 | h3 { 64 | font-family: Arial, Helvetica, sans-serif; 65 | padding: 4px 4px 4px 0; 66 | color: #999 !important; 67 | background: none; 68 | font-weight: none; 69 | font-size: 20px; 70 | border: none; 71 | border-bottom: 1px dotted #ccc; 72 | } 73 | 74 | p { 75 | line-height: 1.3em; 76 | font-size: 12px; 77 | color: #000; 78 | } 79 | 80 | #breadcrumbs { 81 | height: 20px; 82 | padding: 5px 10px 3px 20px; 83 | border: none; 84 | } 85 | 86 | #breadcrumbs a { 87 | font-weight: bold; 88 | color: #999; 89 | text-decoration: underline; 90 | } 91 | 92 | * html #breadcrumbs { 93 | padding-bottom: 8px; 94 | } 95 | 96 | #leftColumn { 97 | margin: 10px 0 10px 2px; 98 | border: 1px solid #ccc; 99 | border-left: none; 100 | padding-right: 5px; 101 | padding-left: 5px; 102 | padding-right: 5px; 103 | border-radius: 14px; 104 | -moz-border-radius: 14px !important; 105 | } 106 | 107 | #navcolumn h5 { 108 | font-size: 11px; 109 | padding-top: 2px; 110 | padding-left: 9px; 111 | color: #999; 112 | font-variant: small-caps; 113 | border: none; 114 | } 115 | 116 | table.bodyTable th { 117 | color: white; 118 | background-color: #bbb; 119 | text-align: left; 120 | font-weight: bold; 121 | } 122 | 123 | table.bodyTable th,table.bodyTable td { 124 | font-size: 11px; 125 | } 126 | 127 | table.bodyTable tr.a { 128 | background-color: #ddd; 129 | } 130 | 131 | table.bodyTable tr.b { 132 | background-color: #eee; 133 | } 134 | 135 | .source { 136 | border: 1px solid #999; 137 | overflow: auto; 138 | background-color: #eee; 139 | border-radius: 14px; 140 | -moz-border-radius: 14px !important; 141 | } 142 | 143 | dt { 144 | padding: 4px 4px 4px 24px; 145 | color: #333333; 146 | background-color: #ccc; 147 | font-weight: bold; 148 | font-size: 14px; 149 | } 150 | 151 | .subsectionTitle { 152 | font-size: 13px; 153 | font-weight: bold; 154 | color: #666; 155 | } 156 | 157 | table { 158 | font-size: 10px; 159 | } 160 | 161 | .xright a:link,.xright a:visited,.xright a:active { 162 | color: #666; 163 | } 164 | 165 | .xright a:hover { 166 | color: #003300; 167 | } 168 | 169 | #navcolumn ul { 170 | margin: 5px 0 15px -0em; 171 | } 172 | 173 | #navcolumn ul a { 174 | color: #333333; 175 | } 176 | 177 | #navcolumn ul a:hover { 178 | color: red; 179 | } 180 | 181 | #intro { 182 | border: solid #ccc 1px; 183 | margin: 6px 0px 0px 0px; 184 | padding: 10px 40px 10px 40px; 185 | } 186 | 187 | .subsection { 188 | margin-left: 3px; 189 | color: #333333; 190 | } 191 | 192 | .subsection p { 193 | font-size: 12px; 194 | } 195 | 196 | #footer { 197 | padding: 10px; 198 | margin: 20px 0px 20px 0px; 199 | border-top: solid #ccc 1px; 200 | color: #333333; 201 | } 202 | /* 203 | #banner { 204 | height: 60px; 205 | } 206 | */ 207 | #bannerLeft { 208 | float: left; 209 | border: 1px solid #ccc; 210 | padding: 4px 12px 4px 12px; 211 | margin: 4px 4px 0 0; 212 | background-color: #eee; 213 | border-radius: 14px; 214 | -moz-border-radius: 14px !important; 215 | font-weight: lighter !important; 216 | } 217 | /* 218 | #bannerRight { 219 | float: right; 220 | } 221 | 222 | #bannerRight img { 223 | width: 125px !important; 224 | height: 37px; 225 | display: block; 226 | float: none; 227 | background-color: #eee; 228 | margin: 10px 0 0 10px; 229 | } 230 | */ -------------------------------------------------------------------------------- /src/site/resources/images/close.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidB/yuicompressor-maven-plugin/175bbbdde555f6e6eb4419f352818849da4f8665/src/site/resources/images/close.gif -------------------------------------------------------------------------------- /src/site/resources/images/collapsed.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidB/yuicompressor-maven-plugin/175bbbdde555f6e6eb4419f352818849da4f8665/src/site/resources/images/collapsed.gif -------------------------------------------------------------------------------- /src/site/resources/images/expanded.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidB/yuicompressor-maven-plugin/175bbbdde555f6e6eb4419f352818849da4f8665/src/site/resources/images/expanded.gif -------------------------------------------------------------------------------- /src/site/resources/images/external.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidB/yuicompressor-maven-plugin/175bbbdde555f6e6eb4419f352818849da4f8665/src/site/resources/images/external.png -------------------------------------------------------------------------------- /src/site/resources/images/icon_error_sml.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidB/yuicompressor-maven-plugin/175bbbdde555f6e6eb4419f352818849da4f8665/src/site/resources/images/icon_error_sml.gif -------------------------------------------------------------------------------- /src/site/resources/images/icon_info_sml.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidB/yuicompressor-maven-plugin/175bbbdde555f6e6eb4419f352818849da4f8665/src/site/resources/images/icon_info_sml.gif -------------------------------------------------------------------------------- /src/site/resources/images/icon_success_sml.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidB/yuicompressor-maven-plugin/175bbbdde555f6e6eb4419f352818849da4f8665/src/site/resources/images/icon_success_sml.gif -------------------------------------------------------------------------------- /src/site/resources/images/icon_warning_sml.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidB/yuicompressor-maven-plugin/175bbbdde555f6e6eb4419f352818849da4f8665/src/site/resources/images/icon_warning_sml.gif -------------------------------------------------------------------------------- /src/site/resources/images/logos/build-by-maven-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidB/yuicompressor-maven-plugin/175bbbdde555f6e6eb4419f352818849da4f8665/src/site/resources/images/logos/build-by-maven-black.png -------------------------------------------------------------------------------- /src/site/resources/images/logos/build-by-maven-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidB/yuicompressor-maven-plugin/175bbbdde555f6e6eb4419f352818849da4f8665/src/site/resources/images/logos/build-by-maven-white.png -------------------------------------------------------------------------------- /src/site/resources/images/logos/maven-feather.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidB/yuicompressor-maven-plugin/175bbbdde555f6e6eb4419f352818849da4f8665/src/site/resources/images/logos/maven-feather.png -------------------------------------------------------------------------------- /src/site/resources/images/newwindow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidB/yuicompressor-maven-plugin/175bbbdde555f6e6eb4419f352818849da4f8665/src/site/resources/images/newwindow.png -------------------------------------------------------------------------------- /src/site/site.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ${project.name} 5 | ${project.url} 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /src/site/template-site.vm: -------------------------------------------------------------------------------- 1 | 2 | 3 | #macro ( link $href $name $target $img $position $alt $border $width $height ) 4 | #set ( $linkTitle = ' title="' + $name + '"' ) 5 | #if( $target ) 6 | #set ( $linkTarget = ' target="' + $target + '"' ) 7 | #else 8 | #set ( $linkTarget = "" ) 9 | #end 10 | #if ( ( $href.toLowerCase().startsWith("http") || $href.toLowerCase().startsWith("https") ) ) 11 | #set ( $linkClass = ' class="externalLink"' ) 12 | #else 13 | #set ( $linkClass = "" ) 14 | #end 15 | #if ( $img ) 16 | #if ( $position == "left" ) 17 | #image($img $alt $border $width $height)$name 18 | #else 19 | $name #image($img $alt $border $width $height) 20 | #end 21 | #else 22 | $name 23 | #end 24 | #end 25 | ## 26 | #macro ( image $img $alt $border $width $height ) 27 | #if( $img ) 28 | #if ( ! ( $img.toLowerCase().startsWith("http") || $img.toLowerCase().startsWith("https") ) ) 29 | #set ( $imgSrc = $PathTool.calculateLink( $img, $relativePath ) ) 30 | #set ( $imgSrc = $imgSrc.replaceAll( '\\', '/' ) ) 31 | #set ( $imgSrc = ' src="' + $imgSrc + '"' ) 32 | #else 33 | #set ( $imgSrc = ' src="' + $img + '"' ) 34 | #end 35 | #if( $alt ) 36 | #set ( $imgAlt = ' alt="' + $alt + '"' ) 37 | #else 38 | #set ( $imgAlt = ' alt=""' ) 39 | #end 40 | #if( $border ) 41 | #set ( $imgBorder = ' border="' + $border + '"' ) 42 | #else 43 | #set ( $imgBorder = "" ) 44 | #end 45 | #if( $width ) 46 | #set ( $imgWidth = ' width="' + $width + '"' ) 47 | #else 48 | #set ( $imgWidth = "" ) 49 | #end 50 | #if( $height ) 51 | #set ( $imgHeight = ' height="' + $height + '"' ) 52 | #else 53 | #set ( $imgHeight = "" ) 54 | #end 55 | 56 | #end 57 | #end 58 | #macro ( banner $banner $id ) 59 | #if ( $banner ) 60 | #if( $banner.href ) 61 | 62 | #else 63 | 86 | #end 87 | #end 88 | #end 89 | ## 90 | #macro ( links $links ) 91 | #set ( $counter = 0 ) 92 | #foreach( $item in $links ) 93 | #set ( $counter = $counter + 1 ) 94 | #set ( $currentItemHref = $PathTool.calculateLink( $item.href, $relativePath ) ) 95 | #set ( $currentItemHref = $currentItemHref.replaceAll( '\\', '/' ) ) 96 | #link( $currentItemHref $item.name $item.target $item.img $item.position $item.alt $item.border $item.width $item.height ) 97 | #if ( $links.size() > $counter ) 98 | | 99 | #end 100 | #end 101 | #end 102 | ## 103 | #macro ( breadcrumbs $breadcrumbs ) 104 | #set ( $counter = 0 ) 105 | #foreach( $item in $breadcrumbs ) 106 | #set ( $counter = $counter + 1 ) 107 | #set ( $currentItemHref = $PathTool.calculateLink( $item.href, $relativePath ) ) 108 | #set ( $currentItemHref = $currentItemHref.replaceAll( '\\', '/' ) ) 109 | ## 110 | #if ( $currentItemHref == $alignedFileName || $currentItemHref == "" ) 111 | $item.name 112 | #else 113 | #link( $currentItemHref $item.name $item.target $item.img $item.position $item.alt $item.border $item.width $item.height ) 114 | #end 115 | #if ( $breadcrumbs.size() > $counter ) 116 | > 117 | #end 118 | #end 119 | #end 120 | ## 121 | #macro ( displayTree $display $item ) 122 | #if ( $item && $item.items && $item.items.size() > 0 ) 123 | #foreach( $subitem in $item.items ) 124 | #set ( $subitemHref = $PathTool.calculateLink( $subitem.href, $relativePath ) ) 125 | #set ( $subitemHref = $subitemHref.replaceAll( '\\', '/' ) ) 126 | #if ( $alignedFileName == $subitemHref ) 127 | #set ( $display = true ) 128 | #end 129 | ## 130 | #displayTree( $display $subitem ) 131 | #end 132 | #end 133 | #end 134 | ## 135 | #macro ( menuItem $item ) 136 | #set ( $collapse = "none" ) 137 | #set ( $currentItemHref = $PathTool.calculateLink( $item.href, $relativePath ) ) 138 | #set ( $currentItemHref = $currentItemHref.replaceAll( '\\', '/' ) ) 139 | ## 140 | #if ( $item && $item.items && $item.items.size() > 0 ) 141 | #if ( $item.collapse == false ) 142 | #set ( $collapse = "expanded" ) 143 | #else 144 | ## By default collapsed 145 | #set ( $collapse = "collapsed" ) 146 | #end 147 | ## 148 | #set ( $display = false ) 149 | #displayTree( $display $item ) 150 | ## 151 | #if ( $alignedFileName == $currentItemHref || $display ) 152 | #set ( $collapse = "expanded" ) 153 | #end 154 | #end 155 |
  • 156 | #if ( $item.img ) 157 | #if ( $item.position == "left" ) 158 | #if ( $alignedFileName == $currentItemHref ) 159 | #image($item.img $item.alt $item.border $item.width $item.height) $item.name 160 | #else 161 | #link($currentItemHref $item.name $item.target $item.img $item.position $item.alt $item.border $item.width $item.height) 162 | #end 163 | #else 164 | #if ( $alignedFileName == $currentItemHref ) 165 | $item.name #image($item.img $item.alt $item.border $item.width $item.height) 166 | #else 167 | #link($currentItemHref $item.name $item.target $item.img $item.position $item.alt $item.border $item.width $item.height) 168 | #end 169 | #end 170 | #else 171 | #if ( $alignedFileName == $currentItemHref ) 172 | $item.name 173 | #else 174 | #link( $currentItemHref $item.name $item.target $item.img $item.position $item.alt $item.border $item.width $item.height ) 175 | #end 176 | #end 177 | #if ( $item && $item.items && $item.items.size() > 0 ) 178 | #if ( $collapse == "expanded" ) 179 |
      180 | #foreach( $subitem in $item.items ) 181 | #menuItem( $subitem ) 182 | #end 183 |
    184 | #end 185 | #end 186 |
  • 187 | #end 188 | ## 189 | #macro ( mainMenu $menus ) 190 | #foreach( $menu in $menus ) 191 | #if ( $menu.name ) 192 | #if ( $menu.img ) 193 | #if( $menu.position ) 194 | #set ( $position = $menu.position ) 195 | #else 196 | #set ( $position = "left" ) 197 | #end 198 | ## 199 | #if ( ! ( $menu.img.toLowerCase().startsWith("http") || $menu.img.toLowerCase().startsWith("https") ) ) 200 | #set ( $src = $PathTool.calculateLink( $menu.img, $relativePath ) ) 201 | #set ( $src = $src.replaceAll( '\\', '/' ) ) 202 | #set ( $src = ' src="' + $src + '"' ) 203 | #else 204 | #set ( $src = ' src="' + $menu.img + '"' ) 205 | #end 206 | ## 207 | #if( $menu.alt ) 208 | #set ( $alt = ' alt="' + $menu.alt + '"' ) 209 | #else 210 | #set ( $alt = ' alt="' + $menu.name + '"' ) 211 | #end 212 | ## 213 | #if( $menu.border ) 214 | #set ( $border = ' border="' + $menu.border + '"' ) 215 | #else 216 | #set ( $border = ' border="0"' ) 217 | #end 218 | ## 219 | #if( $menu.width ) 220 | #set ( $width = ' width="' + $menu.width + '"' ) 221 | #else 222 | #set ( $width = "" ) 223 | #end 224 | #if( $menu.height ) 225 | #set ( $height = ' height="' + $menu.height + '"' ) 226 | #else 227 | #set ( $height = "" ) 228 | #end 229 | ## 230 | #set ( $img = '" ) 231 | ## 232 | #if ( $position == "left" ) 233 |
    $img $menu.name
    234 | #else 235 |
    $menu.name $img
    236 | #end 237 | #else 238 |
    $menu.name
    239 | #end 240 | #end 241 | #if ( $menu.items && $menu.items.size() > 0 ) 242 |
      243 | #foreach( $item in $menu.items ) 244 | #menuItem( $item ) 245 | #end 246 |
    247 | #end 248 | #end 249 | #end 250 | ## 251 | #macro ( copyright ) 252 | #if ( $project ) 253 | #if ( ${project.organization} && ${project.organization.name} ) 254 | #set ( $period = "" ) 255 | #else 256 | #set ( $period = "." ) 257 | #end 258 | ## 259 | #set ( $currentYear = ${currentDate.year} + 1900 ) 260 | ## 261 | #if ( ${project.inceptionYear} && ( ${project.inceptionYear} != ${currentYear.toString()} ) ) 262 | ${project.inceptionYear}-${currentYear}${period} 263 | #else 264 | ${currentYear}${period} 265 | #end 266 | ## 267 | #if ( ${project.organization} ) 268 | #if ( ${project.organization.name} && ${project.organization.url} ) 269 | ${project.organization.name}. 270 | #elseif ( ${project.organization.name} ) 271 | ${project.organization.name}. 272 | #end 273 | #end 274 | #end 275 | #end 276 | ## 277 | #macro ( publishDate $position $publishDate $version ) 278 | #if ( $publishDate && $publishDate.format ) 279 | #set ( $format = $publishDate.format ) 280 | #else 281 | #set ( $format = "yyyy-MM-dd" ) 282 | #end 283 | ## 284 | $dateFormat.applyPattern( $format ) 285 | ## 286 | #set ( $dateToday = $dateFormat.format( $currentDate ) ) 287 | ## 288 | #if ( $publishDate && $publishDate.position ) 289 | #set ( $datePosition = $publishDate.position ) 290 | #else 291 | #set ( $datePosition = "left" ) 292 | #end 293 | ## 294 | #if ( $version ) 295 | #if ( $version.position ) 296 | #set ( $versionPosition = $version.position ) 297 | #else 298 | #set ( $versionPosition = "left" ) 299 | #end 300 | #else 301 | #set ( $version = "" ) 302 | #set ( $versionPosition = "left" ) 303 | #end 304 | ## 305 | #set ( $breadcrumbs = $decoration.body.breadcrumbs ) 306 | #set ( $links = $decoration.body.links ) 307 | 308 | #if ( $datePosition.equalsIgnoreCase( "right" ) && $links && $links.size() > 0 ) 309 | #set ( $prefix = " |" ) 310 | #else 311 | #set ( $prefix = "" ) 312 | #end 313 | ## 314 | #if ( $datePosition.equalsIgnoreCase( $position ) ) 315 | #if ( ( $datePosition.equalsIgnoreCase( "right" ) ) || ( $datePosition.equalsIgnoreCase( "bottom" ) ) ) 316 | $prefix $i18n.getString( "site-renderer", $locale, "template.lastpublished" ): $dateToday 317 | #if ( $versionPosition.equalsIgnoreCase( $position ) ) 318 |  | $i18n.getString( "site-renderer", $locale, "template.version" ): ${project.version} 319 | #end 320 | #elseif ( ( $datePosition.equalsIgnoreCase( "navigation-bottom" ) ) || ( $datePosition.equalsIgnoreCase( "navigation-top" ) ) ) 321 |
    322 | $i18n.getString( "site-renderer", $locale, "template.lastpublished" ): $dateToday 323 | #if ( $versionPosition.equalsIgnoreCase( $position ) ) 324 |  | $i18n.getString( "site-renderer", $locale, "template.version" ): ${project.version} 325 | #end 326 |
    327 | #elseif ( $datePosition.equalsIgnoreCase("left") ) 328 |
    329 | $i18n.getString( "site-renderer", $locale, "template.lastpublished" ): $dateToday 330 | #if ( $versionPosition.equalsIgnoreCase( $position ) ) 331 |  | $i18n.getString( "site-renderer", $locale, "template.version" ): ${project.version} 332 | #end 333 | #if ( $breadcrumbs && $breadcrumbs.size() > 0 ) 334 | | #breadcrumbs( $breadcrumbs ) 335 | #end 336 |
    337 | #end 338 | #elseif ( $versionPosition.equalsIgnoreCase( $position ) ) 339 | #if ( ( $versionPosition.equalsIgnoreCase( "right" ) ) || ( $versionPosition.equalsIgnoreCase( "bottom" ) ) ) 340 | $prefix $i18n.getString( "site-renderer", $locale, "template.version" ): ${project.version} 341 | #elseif ( ( $versionPosition.equalsIgnoreCase( "navigation-bottom" ) ) || ( $versionPosition.equalsIgnoreCase( "navigation-top" ) ) ) 342 |
    343 | $i18n.getString( "site-renderer", $locale, "template.version" ): ${project.version} 344 |
    345 | #elseif ( $versionPosition.equalsIgnoreCase("left") ) 346 |
    347 | $i18n.getString( "site-renderer", $locale, "template.version" ): ${project.version} 348 | #if ( $breadcrumbs && $breadcrumbs.size() > 0 ) 349 | | #breadcrumbs( $breadcrumbs ) 350 | #end 351 |
    352 | #end 353 | #elseif ( $position.equalsIgnoreCase( "left" ) ) 354 | #if ( $breadcrumbs && $breadcrumbs.size() > 0 ) 355 |
    356 | #breadcrumbs( $breadcrumbs ) 357 |
    358 | #end 359 | #end 360 | #end 361 | ## 362 | #macro ( poweredByLogo $poweredBy ) 363 | #if( $poweredBy ) 364 | #foreach ($item in $poweredBy) 365 | #if( $item.href ) 366 | #set ( $href = $PathTool.calculateLink( $item.href, $relativePath ) ) 367 | #set ( $href = $href.replaceAll( '\\', '/' ) ) 368 | #else 369 | #set ( $href="http://maven.apache.org/" ) 370 | #end 371 | ## 372 | #if( $item.name ) 373 | #set ( $name = $item.name ) 374 | #else 375 | #set ( $name = $i18n.getString( "site-renderer", $locale, "template.builtby" ) ) 376 | #set ( $name = "${name} Maven" ) 377 | #end 378 | ## 379 | #if( $item.img ) 380 | #set ( $img = $item.img ) 381 | #else 382 | #set ( $img = "images/logos/maven-feather.png" ) 383 | #end 384 | ## 385 | #if ( ! ( $img.toLowerCase().startsWith("http") || $img.toLowerCase().startsWith("https") ) ) 386 | #set ( $img = $PathTool.calculateLink( $img, $relativePath ) ) 387 | #set ( $img = $src.replaceAll( '\\', '/' ) ) 388 | #end 389 | ## 390 | #if( $item.alt ) 391 | #set ( $alt = ' alt="' + $item.alt + '"' ) 392 | #else 393 | #set ( $alt = ' alt="' + $name + '"' ) 394 | #end 395 | ## 396 | #if( $item.border ) 397 | #set ( $border = ' border="' + $item.border + '"' ) 398 | #else 399 | #set ( $border = "" ) 400 | #end 401 | ## 402 | #if( $item.width ) 403 | #set ( $width = ' width="' + $item.width + '"' ) 404 | #else 405 | #set ( $width = "" ) 406 | #end 407 | #if( $item.height ) 408 | #set ( $height = ' height="' + $item.height + '"' ) 409 | #else 410 | #set ( $height = "" ) 411 | #end 412 | ## 413 | 414 | 415 | 416 | #end 417 | #if( $poweredBy.isEmpty() ) 418 | 419 | $i18n.getString( 420 | 421 | #end 422 | #else 423 | 424 | $i18n.getString( 425 | 426 | #end 427 | #end 428 | ## 429 | 430 | 431 | 432 | $title 433 | 438 | 439 | #foreach( $author in $authors ) 440 | 441 | #end 442 | #if ( $dateCreation ) 443 | 444 | #end 445 | #if ( $dateRevision ) 446 | 447 | #end 448 | #if ( $locale ) 449 | 450 | #end 451 | #if ( $decoration.body.head ) 452 | #foreach( $item in $decoration.body.head.getChildren() ) 453 | ## Workaround for DOXIA-150 due to a non-desired behaviour in p-u 454 | ## @see org.codehaus.plexus.util.xml.Xpp3Dom#toString() 455 | ## @see org.codehaus.plexus.util.xml.Xpp3Dom#toUnescapedString() 456 | #set ( $documentHeader = '' ) 457 | #if ( $item.name == "script" ) 458 | $StringUtils.replace( $item.toUnescapedString(), $documentHeader, "" ) 459 | #else 460 | $StringUtils.replace( $item.toString(), $documentHeader, "" ) 461 | #end 462 | #end 463 | #end 464 | $headContent 465 | 478 | 479 | 480 | 487 | 494 |
    495 | 501 |
    502 |
    503 |
    504 | $bodyContent 505 |
    506 |
    507 |
    508 |
    509 |
    510 | 516 | 517 | 518 | -------------------------------------------------------------------------------- /src/site/xdoc/ex_aggregation.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | David Bernard 4 | 5 | 6 |
    7 |

    Good practice : 8 |

      9 |
    • on web, is to download/call one big js file instead of several small files.
    • 10 |
    • in source code organisation is to have unit file (with one "concern").
    • 11 |
    12 |

    13 |

    The major js and css framework/lib provide source code in both version (one big, lot of small), or provide a online tool to generate the big.

    14 |

    The following option allow you to use/store small files into your source and generate the big at build time. The aggregation is done after yuicompression

    15 | 16 | 17 |

    To Compress every js and css files and aggregate every js file under ${project.build.directory}/${project.build.finalName}/static/ into all.js : 18 | 20 | ... 21 | 22 | 23 | ... 24 | 25 | net.alchim31.maven 26 | yuicompressor-maven-plugin 27 | 28 | 29 | 30 | compress 31 | 32 | 33 | 34 | 35 | true 36 | 37 | 38 | 41 | 42 | true 43 | ${project.build.directory}/${project.build.finalName}/static/all.js 44 | 45 | 46 | 47 | ${basedir}/src/licenses/license.js 48 | **/*.js 49 | 50 | 56 | 57 | 58 | 59 | 60 | ... 61 | 62 | 63 | ... 64 | 65 | ]]> 66 |

    67 |
    68 | 69 | 70 |

    Using removeIncluded option, remove file, but the war plugin will then add file. 71 | So if you want to remove file after aggregation and don't want war plugin copy them, then you need to use warSourceExcludes : 72 | 74 | ... 75 | 76 | 77 | ... 78 | 79 | net.alchim31.maven 80 | yuicompressor-maven-plugin 81 | 82 | 83 | 84 | compress 85 | 86 | 87 | 88 | 89 | true 90 | 91 | 92 | 93 | true 94 | 95 | true 96 | ${project.build.directory}/${project.build.finalName}/static/all-2.js 97 | 98 | 99 | toAggregateAndRemove/**.js 100 | 101 | 102 | 103 | 104 | 105 | ... 106 | 107 | org.apache.maven.plugins 108 | maven-war-plugin 109 | 110 | **/toAggregateAndRemove/** 111 | 112 | 113 | ... 114 | 115 | 116 | ... 117 | 118 | ]]> 119 |

    120 |
    121 | 122 |

    When aggregating minified js files, the copyright headers have been stripped out which is fine because we don't want to repeat it several times in the output file. 123 | However it would be great to be able to insert one at beginning of output file. 124 |

    125 |

    For simple cases, the maven-license-plugin is enough if you use the same header for all files but it is not enough if you want to have a different header per aggregation (different libraries with different licensing schemes).

    126 |
      127 |
    1. you put license header in its own file (ex license_js.txt)
    2. 128 |
    3. aggregate a license header to minified files.
    4. 129 |
    130 | 132 | ${project.build.sourceDirectory}/../webapp/js/mylib/copyright.txt 133 | mylib/**/*.js 134 | 135 | ]]> 136 | 137 |
    138 | 139 |

    When aggregating minified js or css files, the file headers have been stripped out. 140 | However it would be great to be able to easily identify the corresponding input files when looking at the aggregated file. 141 | 143 | ... 144 | 145 | 146 | ... 147 | 148 | net.alchim31.maven 149 | yuicompressor-maven-plugin 150 | 151 | 152 | 153 | compress 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | true 162 | 163 | true 164 | ${project.build.directory}/${project.build.finalName}/static/all-3.js 165 | 166 | 167 | **/*.js 168 | 169 | 170 | 171 | 172 | 173 | ... 174 | 175 | 176 | ... 177 | 178 | ]]> 179 |

    180 |
    181 | 182 |

    When multiple aggregations are defined for the same type of file, such as css, it can be tedious to maintain matching exclusions on the final aggregation which uses a wildcard inclusion. 183 | It would be convenient to automatically exclude wildcard matches that have been included in previous aggregations. 184 | 186 | ... 187 | 188 | 189 | ... 190 | 191 | net.alchim31.maven 192 | yuicompressor-maven-plugin 193 | 194 | 195 | 196 | compress 197 | 198 | 199 | 200 | 201 | 202 | 203 | ${project.build.directory}/${project.build.finalName}/static/IE.css 204 | 205 | 206 | **/IE*.css 207 | 208 | 209 | 210 | 211 | true 212 | ${project.build.directory}/${project.build.finalName}/static/everything-except-IE.css 213 | 214 | 215 | **/*.css 216 | 217 | 218 | 219 | 220 | 221 | ... 222 | 223 | 224 | ... 225 | 226 | ]]> 227 |

    228 |
    229 |
    230 | 231 |
    232 | -------------------------------------------------------------------------------- /src/site/xdoc/ex_failOnWarning.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | David Bernard 4 | 5 | 6 |
    7 |

    FailOnWarning allow to stop the build process if some warning are raise.

    8 |

    To Compress every js and css files and fail if warning (on jslint and/or compress): 9 | 11 | ... 12 | 13 | 14 | ... 15 | 16 | net.alchim31.maven 17 | yuicompressor-maven-plugin 18 | 19 | 20 | 21 | jslint 22 | compress 23 | 24 | 25 | 26 | 27 | true 28 | 29 | 30 | ... 31 | 32 | 33 | ... 34 | 35 | ]]> 36 |

    37 |
    38 | 39 |
    40 | -------------------------------------------------------------------------------- /src/site/xdoc/ex_gzip.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | David Bernard 4 | 5 | 6 |
    7 | 8 |

    To Compress every js and css files and generate a gzipped version (gzip option doesn't remove input file): 9 | 11 | ... 12 | 13 | 14 | ... 15 | 16 | net.alchim31.maven 17 | yuicompressor-maven-plugin 18 | 19 | 20 | 21 | compress 22 | 23 | 24 | 25 | 26 | true 27 | 28 | 29 | ... 30 | 31 | 32 | ... 33 | 34 | ]]> 35 |

    36 |
    37 | 38 |
    39 | -------------------------------------------------------------------------------- /src/site/xdoc/index.xml.vm: -------------------------------------------------------------------------------- 1 | 2 | 3 | David Bernard 4 | 5 | 6 | 7 | 8 |
    9 |

    10 |

      11 |
    • Repository : http://oss.sonatype.org/content/groups/public (since version 1.0, available on central repository)
    • 12 |
    • GroupId : ${project.groupId} (changed since 0.9)
    • 13 |
    • ArtifactId : ${project.artifactId}
    • 14 |
    • ArtifactId : ${project.version}
    • 15 |
    16 |

    17 | 19 | 20 | oss.sonatype.org 21 | oss.sonatype.org 22 | http://oss.sonatype.org/content/groups/public 23 | 24 | 25 | ... 26 | 27 | 28 | ${project.groupId} 29 | ${project.artifactId} 30 | ${project.version} 31 | ... 32 | 33 | ... 34 | ]]> 35 | 36 |
    37 | 38 |
    39 | 40 | 41 |

    Compress (Minify + Ofuscate) Javascript files and CSS files 42 | using YUI Compressor from Julien Lecomte. 43 | Because Javascript compression could need time and resource, and to avoid repetitive (stupid) resources consumming at runtime, this plugin do compression of static files at compile time . 44 |

      45 |
    • Compression is applied on webapp dir (src/main/webapp) and on resources (usefull for framework like Wicket where js and css could be in jar).
    • 46 |
    • Compressed Files are renamed with a suffix (default "-min"), so both version are available (compressed and original) in the targeting application, but if you don't want to keep original and want to overwrite it set option 'nosuffix' to 'true'.
    • 47 |
    • there are other options see details.
    • 48 |
    49 |

    50 |
    51 | 52 | 53 |

    Check Javascript file with jslint

    54 |
    55 | 56 | 57 |

    58 | A sample output extract from my working project : 59 | uni-form-generic-min.css (1625b)[33%] 62 | [INFO] uni-form.css (8431b) -> uni-form-min.css (3435b)[40%] 63 | [WARNING] .../src/main/webapp/static/uni-form/js/highlighter.js:line -1:column -1:Found an undeclared symbol: i 64 | Highlighter.settings.field_class);for(i ---> = <--- 0;i highlighter-min.js (1625b)[50%] 66 | [WARNING] .../src/main/webapp/static/uni-form/js/uni-form.jquery.js:line -1:column -1:Found an undeclared symbol: $ 67 | ;});});};$ ---> ( <--- document).ready(function (){ 68 | [INFO] uni-form.jquery.js (1261b) -> uni-form.jquery-min.js (674b)[53%] 69 | [INFO] style.css (11620b) -> style-min.css (8474b)[72%] 70 | [INFO] buttons.css (2513b) -> buttons-min.css (1227b)[48%] 71 | [INFO] grid.css (5012b) -> grid-min.css (2003b)[39%] 72 | [INFO] reset.css (1164b) -> reset-min.css (642b)[55%] 73 | [INFO] typography.css (5136b) -> typography-min.css (1800b)[35%] 74 | [INFO] print.css (1568b) -> print-min.css (631b)[40%] 75 | [INFO] screen.css (1035b) -> screen-min.css (103b)[9%] 76 | [INFO] navbar.css (653b) -> navbar-min.css (460b)[70%] 77 | [INFO] total input (46508b) -> output (22699b)[48%] 78 | [INFO] nb warnings: 2, nb errors: 0 79 | [INFO] ------------------------------------------------------------------------ 80 | [INFO] BUILD SUCCESSFUL 81 | [INFO] ------------------------------------------------------------------------ 82 | [INFO] Total time: 1 second 83 | [INFO] Finished at: Tue Aug 28 23:40:57 CEST 2007 84 | [INFO] Final Memory: 12M/21M 85 | [INFO] ------------------------------------------------------------------------ 86 | ]]> 87 |

    88 |
    89 |
    90 | 91 | 92 | 93 |
    94 | -------------------------------------------------------------------------------- /src/site/xdoc/links.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | David Bernard 4 | 5 | 6 | 7 |
    8 | 9 | 12 | 13 | 14 | 15 | 23 | 24 | 25 | 26 | 32 | 33 | 34 | 35 |
      36 |
    • MobilVox Maven JavaScript Plugin: compress javascript file of a project
    • 37 |
    • JAWR: awr is a tunable packaging solution for Javascript and CSS which allows for rapid development of resources in separate module files
    • 38 |
    • wro4j: Web Resource Optimizer for Java
    • 39 |
    • zipper: Zipper is a full-featured asset packaging plugin for Maven that aims at optimiziing your project's static resources at build time.
    • 40 |
    • jslint-maven-plugin: A simple Maven plugin to run jslint4java as part of the maven test phase. If jslint finds any problems, it will fail the build.
    • 41 |
    • jslint-plugin: This plugin brings JSLint capabilities to the Maven project lifecycle with the goal of assuring JavaScript code quality.
    • 42 |
    43 |
    44 | 45 |
    46 | 47 |
    48 | -------------------------------------------------------------------------------- /src/site/xdoc/usage_compress.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | David Bernard 4 | 5 | 6 |
    7 | 8 | 9 |

    To Compress every js and css files : 10 | mvn net.alchim31.maven:yuicompressor-maven-plugin:compress 12 | ]]> 13 | with the -X option compressed file are listed. 14 |

    15 | 16 |

    To force compress every js and css files and fail if warning : 17 | mvn net.alchim31.maven:yuicompressor-maven-plugin:compress \ 19 | -Dmaven.yuicompressor.force=true \ 20 | -Dmaven.yuicompressor.failOnWarning=true \ 21 | ]]> 22 |

    23 |
    24 | 25 | 26 | 27 | 28 |

    To Compress every js and css files at process-resources phase (before compile) : 29 | 31 | ... 32 | 33 | 34 | ... 35 | 36 | net.alchim31.maven 37 | yuicompressor-maven-plugin 38 | 39 | 40 | 41 | compress 42 | 43 | 44 | 45 | 46 | ... 47 | 48 | 49 | ... 50 | 51 | ]]> 52 |

    53 | 54 |

    To Compress every js and css files but without renaming with suffix : 55 | 57 | ... 58 | 59 | 60 | ... 61 | 62 | net.alchim31.maven 63 | yuicompressor-maven-plugin 64 | 65 | 66 | 67 | compress 68 | 69 | 70 | 71 | 72 | true 73 | 74 | 75 | ... 76 | 77 | 78 | ... 79 | 80 | ]]> 81 |

    82 | 83 |

    To Compress every js and css files except already compressed files like *.pack.js files and compressed.css : 84 | 86 | ... 87 | 88 | 89 | ... 90 | 91 | net.alchim31.maven 92 | yuicompressor-maven-plugin 93 | 94 | 95 | 96 | compress 97 | 98 | 99 | 100 | 101 | 102 | **/*.pack.js 103 | **/compressed.css 104 | 105 | 106 | 107 | ... 108 | 109 | 110 | ... 111 | 112 | ]]> 113 |

    114 |
    115 |
    116 | 117 |
    118 | -------------------------------------------------------------------------------- /src/site/xdoc/usage_jslint.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | David Bernard 4 | 5 | 6 |
    7 | 8 | 9 |

    To Check every js : 10 | mvn net.alchim31.maven:yuicompressor-maven-plugin:jslint 12 | ]]> 13 |

    14 |
    15 | 16 | 17 | 18 | 19 |

    To Check every js : 20 | 22 | ... 23 | 24 | 25 | ... 26 | 27 | net.alchim31.maven 28 | yuicompressor-maven-plugin 29 | 30 | 31 | 32 | jslint 33 | 34 | 35 | 36 | 37 | ... 38 | 39 | 40 | ... 41 | 42 | ]]> 43 |

    44 | 45 |

    To check and compress every js and css files except already compressed files like *.pack.js files and compressed.css : 46 | 48 | ... 49 | 50 | 51 | ... 52 | 53 | net.alchim31.maven 54 | yuicompressor-maven-plugin 55 | 56 | 57 | 58 | jslint 59 | compress 60 | 61 | 62 | 63 | 64 | 65 | **/*.pack.js 66 | **/compressed.css 67 | 68 | 69 | 70 | ... 71 | 72 | 73 | ... 74 | 75 | ]]> 76 |

    77 |
    78 |
    79 | 80 |
    81 | -------------------------------------------------------------------------------- /src/test/java/net_alchim31_maven_yuicompressor/AggregationTestCase.java: -------------------------------------------------------------------------------- 1 | package net_alchim31_maven_yuicompressor; 2 | 3 | import com.google.common.collect.Lists; 4 | import junit.framework.TestCase; 5 | import org.codehaus.plexus.util.FileUtils; 6 | import org.sonatype.plexus.build.incremental.DefaultBuildContext; 7 | 8 | import java.io.File; 9 | import java.util.Collection; 10 | import java.util.HashSet; 11 | 12 | public class AggregationTestCase extends TestCase { 13 | private File dir_; 14 | 15 | private DefaultBuildContext defaultBuildContext = new DefaultBuildContext(); 16 | 17 | @Override 18 | protected void setUp() throws Exception { 19 | dir_ = File.createTempFile(this.getClass().getName(), "-test"); 20 | dir_.delete(); 21 | dir_.mkdirs(); 22 | } 23 | 24 | @Override 25 | protected void tearDown() throws Exception { 26 | FileUtils.deleteDirectory(dir_); 27 | } 28 | 29 | public void test0to1() throws Exception { 30 | Aggregation target = new Aggregation(); 31 | target.output = new File(dir_, "output.js"); 32 | 33 | assertFalse(target.output.exists()); 34 | target.run(null, defaultBuildContext); 35 | assertFalse(target.output.exists()); 36 | 37 | target.includes = new String[]{}; 38 | assertFalse(target.output.exists()); 39 | target.run(null, defaultBuildContext); 40 | assertFalse(target.output.exists()); 41 | 42 | target.includes = new String[]{"**/*.js"}; 43 | assertFalse(target.output.exists()); 44 | target.run(null, defaultBuildContext); 45 | assertFalse(target.output.exists()); 46 | } 47 | 48 | 49 | public void test1to1() throws Exception { 50 | File f1 = new File(dir_, "01.js"); 51 | FileUtils.fileWrite(f1.getAbsolutePath(), "1"); 52 | Aggregation target = new Aggregation(); 53 | target.output = new File(dir_, "output.js"); 54 | target.includes = new String[]{f1.getName()}; 55 | 56 | assertFalse(target.output.exists()); 57 | target.run(null, defaultBuildContext); 58 | assertTrue(target.output.exists()); 59 | assertEquals(FileUtils.fileRead(f1), FileUtils.fileRead(target.output)); 60 | } 61 | 62 | public void test2to1() throws Exception { 63 | File f1 = new File(dir_, "01.js"); 64 | FileUtils.fileWrite(f1.getAbsolutePath(), "1"); 65 | 66 | File f2 = new File(dir_, "02.js"); 67 | FileUtils.fileWrite(f2.getAbsolutePath(), "22\n22"); 68 | 69 | Aggregation target = new Aggregation(); 70 | target.output = new File(dir_, "output.js"); 71 | 72 | target.includes = new String[]{f1.getName(), f2.getName()}; 73 | assertFalse(target.output.exists()); 74 | target.run(null, defaultBuildContext); 75 | assertTrue(target.output.exists()); 76 | assertEquals(FileUtils.fileRead(f1) + FileUtils.fileRead(f2), FileUtils.fileRead(target.output)); 77 | 78 | target.output.delete(); 79 | target.includes = new String[]{"*.js"}; 80 | assertFalse(target.output.exists()); 81 | target.run(null, defaultBuildContext); 82 | assertTrue(target.output.exists()); 83 | assertEquals(FileUtils.fileRead(f1) + FileUtils.fileRead(f2), FileUtils.fileRead(target.output)); 84 | } 85 | 86 | public void testNoDuplicateAggregation() throws Exception { 87 | File f1 = new File(dir_, "01.js"); 88 | FileUtils.fileWrite(f1.getAbsolutePath(), "1"); 89 | 90 | File f2 = new File(dir_, "02.js"); 91 | FileUtils.fileWrite(f2.getAbsolutePath(), "22\n22"); 92 | 93 | Aggregation target = new Aggregation(); 94 | target.output = new File(dir_, "output.js"); 95 | 96 | target.includes = new String[]{f1.getName(), f1.getName(), f2.getName()}; 97 | assertFalse(target.output.exists()); 98 | target.run(null, defaultBuildContext); 99 | assertTrue(target.output.exists()); 100 | assertEquals(FileUtils.fileRead(f1) + FileUtils.fileRead(f2), FileUtils.fileRead(target.output)); 101 | 102 | target.output.delete(); 103 | target.includes = new String[]{f1.getName(), "*.js"}; 104 | assertFalse(target.output.exists()); 105 | target.run(null, defaultBuildContext); 106 | assertTrue(target.output.exists()); 107 | assertEquals(FileUtils.fileRead(f1) + FileUtils.fileRead(f2), FileUtils.fileRead(target.output)); 108 | } 109 | 110 | public void test2to1Order() throws Exception { 111 | File f1 = new File(dir_, "01.js"); 112 | FileUtils.fileWrite(f1.getAbsolutePath(), "1"); 113 | 114 | File f2 = new File(dir_, "02.js"); 115 | FileUtils.fileWrite(f2.getAbsolutePath(), "2"); 116 | 117 | Aggregation target = new Aggregation(); 118 | target.output = new File(dir_, "output.js"); 119 | 120 | target.includes = new String[]{f2.getName(), f1.getName()}; 121 | assertFalse(target.output.exists()); 122 | target.run(null, defaultBuildContext); 123 | assertTrue(target.output.exists()); 124 | assertEquals(FileUtils.fileRead(f2) + FileUtils.fileRead(f1), FileUtils.fileRead(target.output)); 125 | } 126 | 127 | public void test2to1WithNewLine() throws Exception { 128 | File f1 = new File(dir_, "01.js"); 129 | FileUtils.fileWrite(f1.getAbsolutePath(), "1"); 130 | 131 | File f2 = new File(dir_, "02.js"); 132 | FileUtils.fileWrite(f2.getAbsolutePath(), "22\n22"); 133 | 134 | Aggregation target = new Aggregation(); 135 | target.output = new File(dir_, "output.js"); 136 | target.insertNewLine = true; 137 | target.includes = new String[]{f1.getName(), f2.getName()}; 138 | 139 | assertFalse(target.output.exists()); 140 | target.run(null, defaultBuildContext); 141 | assertTrue(target.output.exists()); 142 | assertEquals(FileUtils.fileRead(f1) + "\n" + FileUtils.fileRead(f2) + "\n", FileUtils.fileRead(target.output)); 143 | } 144 | 145 | public void testAbsolutePathFromInside() throws Exception { 146 | File f1 = new File(dir_, "01.js"); 147 | FileUtils.fileWrite(f1.getAbsolutePath(), "1"); 148 | 149 | File f2 = new File(dir_, "02.js"); 150 | FileUtils.fileWrite(f2.getAbsolutePath(), "22\n22"); 151 | 152 | Aggregation target = new Aggregation(); 153 | target.output = new File(dir_, "output.js"); 154 | 155 | target.includes = new String[]{f1.getAbsolutePath(), f2.getName()}; 156 | assertFalse(target.output.exists()); 157 | target.run(null, defaultBuildContext); 158 | assertTrue(target.output.exists()); 159 | assertEquals(FileUtils.fileRead(f1) + FileUtils.fileRead(f2), FileUtils.fileRead(target.output)); 160 | } 161 | 162 | public void testAbsolutePathFromOutside() throws Exception { 163 | File f1 = File.createTempFile("test-01", ".js"); 164 | try { 165 | FileUtils.fileWrite(f1.getAbsolutePath(), "1"); 166 | 167 | File f2 = new File(dir_, "02.js"); 168 | FileUtils.fileWrite(f2.getAbsolutePath(), "22\n22"); 169 | 170 | Aggregation target = new Aggregation(); 171 | target.output = new File(dir_, "output.js"); 172 | 173 | target.includes = new String[]{f1.getAbsolutePath(), f2.getName()}; 174 | assertFalse(target.output.exists()); 175 | target.run(null, defaultBuildContext); 176 | assertTrue(target.output.exists()); 177 | assertEquals(FileUtils.fileRead(f1) + FileUtils.fileRead(f2), FileUtils.fileRead(target.output)); 178 | } finally { 179 | f1.delete(); 180 | } 181 | } 182 | 183 | public void testAutoExcludeWildcards() throws Exception { 184 | File f1 = new File(dir_, "01.js"); 185 | FileUtils.fileWrite(f1.getAbsolutePath(), "1"); 186 | 187 | File f2 = new File(dir_, "02.js"); 188 | FileUtils.fileWrite(f2.getAbsolutePath(), "22\n22"); 189 | 190 | Aggregation target = new Aggregation(); 191 | target.autoExcludeWildcards = true; 192 | target.output = new File(dir_, "output.js"); 193 | 194 | Collection previouslyIncluded = new HashSet(); 195 | previouslyIncluded.add(f1); 196 | 197 | target.includes = new String[]{f1.getName(), f2.getName()}; 198 | assertFalse(target.output.exists()); 199 | target.run(previouslyIncluded, defaultBuildContext); 200 | assertTrue(target.output.exists()); 201 | assertEquals(FileUtils.fileRead(f1) + FileUtils.fileRead(f2), FileUtils.fileRead(target.output)); 202 | 203 | target.output.delete(); 204 | target.includes = new String[]{"*.js"}; 205 | assertFalse(target.output.exists()); 206 | //f1 was in previouslyIncluded so it is not included 207 | assertEquals(target.run(previouslyIncluded, defaultBuildContext), Lists.newArrayList(f2)); 208 | assertTrue(target.output.exists()); 209 | assertEquals(FileUtils.fileRead(f2), FileUtils.fileRead(target.output)); 210 | } 211 | } 212 | --------------------------------------------------------------------------------