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

com.learningobjects.sass.CompileSassMojo Maven / Gradle / Ivy

There is a newer version: 1.1
Show newest version
package com.learningobjects.sass;

import com.cathive.sass.SassCompilationException;
import com.cathive.sass.SassContext;
import com.cathive.sass.SassFileContext;
import com.cathive.sass.SassOptions;
import com.cathive.sass.SassOutputStyle;
import org.apache.commons.io.FilenameUtils;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.codehaus.plexus.util.DirectoryScanner;

import java.io.File;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;

/**
 * Compiles SASS into CSS.
 * 

* This plugin scans for subdirectories of {@code sassSourceDirectory} called {@code sass} containing {@code .scss} * files. For each SASS file, an associated CSS file is created in a relative {@code css} directory under the * {@code cssTargetDirectory}. *

* For example, using the default parameters, if there is a SASS input file at {@code /src/main/resources/com/mycompany/sass/styles.scss}, * then an associated CSS output file will be created at {@code /target/classes/com/mycompany/css/styles.css}. * * @since 1.0 * @author Ben Zoller */ @Mojo(name = "compile", defaultPhase = LifecyclePhase.PROCESS_RESOURCES) public class CompileSassMojo extends AbstractMojo { private static final SassFilenameFilter sassFilenameFilter = new SassFilenameFilter(); /** * Source directory containing one or more {@code sass} sub-directories, which contain one or more {@code .scss} files. * @since 1.0 */ @Parameter(defaultValue = "${basedir}/src/main/resources") private String sassSourceDirectory; /** * Target directory where CSS files will be generated under according to the relative path of the source SASS files. * @since 1.0 */ @Parameter(defaultValue = "${project.build.outputDirectory}") private String cssTargetDirectory; /** * Read-only parameter for the Maven project ${basedir} used for logging. * @since 1.0 */ @Parameter(defaultValue = "${basedir}", readonly = true) private String baseDirectory; /** * Compiles SASS into CSS. */ public void execute() throws MojoExecutionException, MojoFailureException { getLog().info("Compiling SASS into CSS"); Map sassToCssMap = buildSassToCssMap(); try { for (Map.Entry entry : sassToCssMap.entrySet()) { Path sassFilePath = entry.getKey(); Path cssFilePath = entry.getValue(); compileSassToCss(sassFilePath, cssFilePath); } } catch (SassCompilationException | IOException e) { throw new MojoExecutionException("Failed to compile: " + e.getMessage(), e); } } /** * Compiles the specified SASS file into a CSS file according to the specified target file path. */ private void compileSassToCss(Path sassFilePath, Path cssFilePath) throws IOException { logSassToCss(sassFilePath, cssFilePath); Files.createDirectories(cssFilePath.getParent()); SassContext ctx = buildSassContext(sassFilePath); try (FileOutputStream out = new FileOutputStream(cssFilePath.toFile())) { ctx.compile(out); } } private void logSassToCss(Path sassFilePath, Path cssFilePath) { Path basePath = Paths.get(baseDirectory); Path sourceRelative = basePath.relativize(sassFilePath); Path targetRelative = basePath.relativize(cssFilePath); getLog().info(String.format(" %s => %s", sourceRelative, targetRelative)); } private SassContext buildSassContext(Path sassFilePath) { SassContext ctx = SassFileContext.create(sassFilePath); Path sassDirectory = sassFilePath.getParent(); SassOptions options = ctx.getOptions(); options.setIncludePath(sassDirectory); options.setOutputStyle(SassOutputStyle.NESTED); return ctx; } /** * Builds a map of input SASS file path to generated output CSS file path * by scanning the input directory for SASS files. */ private Map buildSassToCssMap() { String[] includedDirectories = getSassDirectories(); Map sassToCssMap = new HashMap<>(); for (String sassDirectoryRelativePath : includedDirectories) { addSassFilesInDirectoryToMap(sassDirectoryRelativePath, sassToCssMap); } return sassToCssMap; } private String[] getSassDirectories() { DirectoryScanner scanner = new DirectoryScanner(); scanner.setBasedir(sassSourceDirectory); scanner.setIncludes(new String[]{"**/sass"}); scanner.addDefaultExcludes(); scanner.scan(); return scanner.getIncludedDirectories(); } private void addSassFilesInDirectoryToMap(String sassDirectoryRelativePath, Map sassToCssMap) { Path sassPath = getSassPath(sassDirectoryRelativePath); Path cssPath = getCssPath(sassPath); File[] sassFiles = sassPath.toFile().listFiles(sassFilenameFilter); for (File sassFile : sassFiles) { addSassFileToMap(sassFile, cssPath, sassToCssMap); } } private Path getSassPath(String sassDirectoryRelativePath) { Path sourcePath = Paths.get(sassSourceDirectory); return sourcePath.resolve(sassDirectoryRelativePath); } private Path getCssPath(Path sassPath) { Path parentPath = sassPath.getParent(); Path sourcePath = Paths.get(sassSourceDirectory); Path relativeParentPath = sourcePath.relativize(parentPath); return Paths.get(cssTargetDirectory).resolve(relativeParentPath).resolve("css"); } private void addSassFileToMap(File sassFile, Path cssPath, Map sassToCssMap) { String sassFilename = sassFile.getName(); Path sassFilePath = sassFile.toPath(); String name = FilenameUtils.removeExtension(sassFilename); String cssFilename = name + ".css"; Path cssFilePath = cssPath.resolve(cssFilename); sassToCssMap.put(sassFilePath, cssFilePath); } /** * Filename filter which accepts {@code .scss} files which do not start with {@code _}. */ private static class SassFilenameFilter implements FilenameFilter { @Override public boolean accept(File dir, String name) { return !name.startsWith("_") && name.endsWith(".scss"); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy