package fr.lteconsulting.hexacssmaven;
import java.io.BufferedWriter;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.maven.plugin.logging.Log;
/**
* Loads a CSS file and a mapping file. Every selector in the css file are
* changed to their mapped name. Selectors in the css file that are not used in
* the mapping file can be pruned (optional).
*/
public class CssMapper
{
/**
* Process an input file
*
* @throws IOException In case there is a problem
*
* @param input
* The input file content
* @param mappingPath
* The file containing mapping information (lines in the form of
* newName=oldName)
* @param outputFile
* Path to the output file
* @param doPrune
* <code>true</code> if pruning unused CSS rules is needed
* @param log
* Maven logger
*/
public static void processFile( String input, String mappingPath, String outputFile, boolean doPrune, Log log ) throws IOException
{
Set<String> usedClassNames = new HashSet<>();
input = replaceClassNames( input, mappingPath, usedClassNames, log );
log.debug( usedClassNames.size() + " used css classes in the mapping file" );
log.debug( "used css classes : " + usedClassNames );
CssRewriter cssRewriter = new CssRewriter( usedClassNames, doPrune, log );
input = cssRewriter.process( input );
input += "\r\n// generated by HexaCss maven plugin, see http://www.lteconsulting.fr/hexacss";
writeFile( outputFile, input, log );
}
private static void writeFile( String path, String content, Log log ) throws IOException
{
Path outputPath = Paths.get( path );
if( Files.exists( outputPath ) )
Files.delete( outputPath );
BufferedWriter writer = Files.newBufferedWriter( outputPath, StandardCharsets.UTF_8, StandardOpenOption.CREATE_NEW );
writer.append( content );
writer.close();
log.info( "Wrote to file " + outputPath );
log.debug( "Output content :" );
log.debug( content );
}
private static String replaceClassNames( String input, String mappingPath, Set<String> usedClassNames, Log log ) throws IOException
{
List<String> lines = Files.readAllLines( Paths.get( mappingPath ), StandardCharsets.UTF_8 );
Set<String> done = new HashSet<>();
List<String[]> renames = new ArrayList<>();
for( String line : lines )
{
String[] parts = line.split( "=" );
if( done.contains( parts[0] ) )
continue;
else
done.add( parts[0] );
renames.add( parts );
}
Collections.sort( renames, new Comparator<String[]>()
{
@Override
public int compare( String[] a, String[] b )
{
return ((Integer) b[1].length()).compareTo( a[1].length() );
}
} );
for( String[] line : renames )
{
log.debug( line[1] + " => " + line[0] );
if( !input.contains( "." + line[1] ) )
log.warn( "not found ." + line[1] + " css rule in the source file, mapping to ." + line[0] );
input = input.replaceAll( "\\." + line[1], "." + line[0] );
usedClassNames.add( line[0] );
}
log.info( renames.size() + " CSS obfuscated rule(s)." );
return input;
}
}