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; } }