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

org.daisy.pipeline.maven.plugin.HtmlizeSourcesMojo Maven / Gradle / Ivy

package org.daisy.pipeline.maven.plugin;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FilenameFilter;
import java.io.FileReader;
import java.io.FileWriter;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import java.util.regex.Matcher;

import com.google.common.base.Function;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Multimap;
import com.google.common.collect.Multimaps;

import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.project.MavenProject;

import org.codehaus.plexus.util.DirectoryScanner;

import org.daisy.maven.xproc.api.XProcEngine;
import org.daisy.maven.xproc.api.XProcExecutionException;

import static org.daisy.pipeline.maven.plugin.utils.URIs.asURI;
import static org.daisy.pipeline.maven.plugin.utils.URIs.relativize;
import static org.daisy.pipeline.maven.plugin.utils.XML.evaluateXPath;
import static org.daisy.pipeline.maven.plugin.utils.XML.transform;
import org.daisy.pipeline.modules.impl.resolver.ModuleUriResolver;

/**
 * @goal htmlize-sources
 * @requiresDependencyResolution compile
 */
public class HtmlizeSourcesMojo extends AbstractMojo {
	
	/**
	 * @parameter expression="${project.basedir}/src/main/resources"
	 * @required
	 */
	private File sourceDirectory;
	
	/**
	 * @parameter expression="${project.basedir}/src/main/resources/META-INF/catalog.xml"
	 * @required
	 */
	private File catalogXmlFile;
	
	/**
	 * @parameter
	 */
	private String includes;
	private final String defaultIncludes = "**/*.xpl,**/*.xsl,**/*.css";
	
	/**
	 * @parameter expression="${project.build.directory}/generated-resources/htmlize-sources"
	 * @required
	 */
	private File outputDirectory;
	
	/**
	 * @parameter expression="${project}"
	 */
	private MavenProject mavenProject;
	
	private final static Pattern PSEUDO_ATTR_RE = Pattern.compile("(href|type|title|media|charset|alternate)=(\"([^\"]+)\"|'([^']+)')");
	private final static Pattern STYLESHEET_RE = Pattern.compile("^\\s*" + PSEUDO_ATTR_RE + "(\\s+" + PSEUDO_ATTR_RE + ")*\\s*$");
	
	public void execute() throws MojoFailureException {
		try {
			final List compileClassPath = mavenProject.getCompileClasspathElements();
			final XProcEngine engine = new CalabashWithPipelineModules(compileClassPath);
			List sources = new ArrayList();
			if (includes == null)
				includes = defaultIncludes;
			DirectoryScanner scanner = new DirectoryScanner();
			scanner.setBasedir(sourceDirectory);
			scanner.setIncludes(includes.replaceAll("\\s", "").split(",(?![^{]*})"));
			scanner.setExcludes(new String[]{"**/.DS_Store"});
			scanner.scan();
			for (String f : scanner.getIncludedFiles())
				sources.add(new File(sourceDirectory, f));
			final Map htmlizers = new HashMap(); {
				final Map> params
					= ImmutableMap.of("parameters",
					                  (Map)ImmutableMap.of("catalog-xml-uri", asURI(catalogXmlFile).toASCIIString()));
				htmlizers.put(
					new FilenameFilter() {
						public boolean accept(File dir, String name) {
							return name.equals("catalog.xml") && dir.getName().equals("META-INF"); }},
					new Htmlizer() {
						public void run(Iterable sources, File sourceDirectory, File outputDirectory) throws XProcExecutionException {
							List sourcesAsURIs = new ArrayList();
							for (File f : sources)
								sourcesAsURIs.add(asURI(f).toASCIIString());
								engine.run(asURI(HtmlizeSourcesMojo.class.getResource("/htmlize-sources/htmlize-catalog.xpl")).toASCIIString(),
								           ImmutableMap.of("sources", sourcesAsURIs),
								           null,
								           ImmutableMap.of("input-base-uri", asURI(sourceDirectory).toASCIIString(),
								                           "output-base-uri", asURI(outputDirectory).toASCIIString()),
								           params);
						}
					}
				);
				htmlizers.put(
					new FilenameFilter() {
						public boolean accept(File dir, String name) {
							return name.endsWith(".xpl"); }},
					new Htmlizer() {
						public void run(Iterable sources, File sourceDirectory, File outputDirectory) throws XProcExecutionException {
							List sourcesAsURIs = new ArrayList();
							for (File f : sources)
								sourcesAsURIs.add(asURI(f).toASCIIString());
								engine.run(asURI(HtmlizeSourcesMojo.class.getResource("/htmlize-sources/htmlize-xproc.xpl")).toASCIIString(),
								           ImmutableMap.of("sources", sourcesAsURIs),
								           null,
								           ImmutableMap.of("input-base-uri", asURI(sourceDirectory).toASCIIString(),
								                           "output-base-uri", asURI(outputDirectory).toASCIIString()),
								           params);
						}
					}
				);
				htmlizers.put(
					new FilenameFilter() {
						public boolean accept(File dir, String name) {
							return name.endsWith(".xsl"); }},
					new Htmlizer() {
						public void run(Iterable sources, File sourceDirectory, File outputDirectory) throws XProcExecutionException {
							List sourcesAsURIs = new ArrayList();
							for (File f : sources)
								sourcesAsURIs.add(asURI(f).toASCIIString());
								engine.run(asURI(HtmlizeSourcesMojo.class.getResource("/htmlize-sources/htmlize-xslt.xpl")).toASCIIString(),
								           ImmutableMap.of("sources", sourcesAsURIs),
								           null,
								           ImmutableMap.of("input-base-uri", asURI(sourceDirectory).toASCIIString(),
								                           "output-base-uri", asURI(outputDirectory).toASCIIString()),
								           params);
						}
					}
				);
				htmlizers.put(
					new FilenameFilter() {
						public boolean accept(File dir, String name) {
							return name.endsWith(".css") || name.endsWith(".scss"); }},
					new Htmlizer() {
						public void run(Iterable sources, File sourceDirectory, File outputDirectory) {
							for (File f : sources) {
								try {
									File outputFile = new File(outputDirectory, relativize(asURI(sourceDirectory), asURI(f)) + "/index.md");
									outputFile.getParentFile().mkdirs();
									BufferedReader reader = new BufferedReader(new FileReader(f));
									BufferedWriter writer = new BufferedWriter(new FileWriter(outputFile));
									writer.write("");
									writer.newLine();
									writer.newLine();
									if (f.getName().endsWith(".scss"))
										writer.write("~~~sass");
									else
										writer.write("~~~css");
									writer.newLine();
									String line;
									while ((line = reader.readLine()) != null) {
										writer.write(line);
										writer.newLine(); }
									writer.write("~~~");
									writer.newLine();
									writer.close();
								} catch (Exception e) {
									throw new RuntimeException("Error processing file " + f, e);
								}
							}
						}
					}
				);
				htmlizers.put(
					new FilenameFilter() {
						public boolean accept(File dir, String name) {
							if (name.endsWith(".xpl") || name.endsWith(".xsl") || (name.equals("catalog.xml") && dir.getName().equals("META-INF")))
								return false;
							File f = new File(dir, name);
							boolean isXml; {
								try {
									isXml = (Boolean)evaluateXPath(f, "/*", null, Boolean.class); }
								catch (RuntimeException e) {
									isXml = false; }}
							return isXml;
						}},
					new Htmlizer() {
						public void run(Iterable sources, File sourceDirectory, File outputDirectory) {
							for (File f : sources) {
								File outputFile = new File(outputDirectory, relativize(asURI(sourceDirectory), asURI(f)) + "/index.html");
								URI xslt; {
									xslt = null;
									String instruction = (String)evaluateXPath(
										f, "/processing-instruction('xml-stylesheet')[1]", null, String.class);
									if (instruction != null) {
										Matcher m = STYLESHEET_RE.matcher(instruction);
										if (m.matches()) {
											m = PSEUDO_ATTR_RE.matcher(instruction);
											while (m.find())
												if ("href".equals(m.group(1))) {
													String href = m.group(3);
													if (href == null) href = m.group(4);
													xslt = asURI(f).resolve(href);
													try {
														if (!(Boolean)evaluateXPath(asURI(f).resolve(href),
														                            "/xsl:stylesheet",
														                            ImmutableMap.of("xsl", "http://www.w3.org/1999/XSL/Transform"),
														                            Boolean.class))
															xslt = null; }
													catch (RuntimeException e) {
														xslt = null; }
													break; }}
									}
								}
								if (xslt != null) {
									transform(f,
									          outputFile,
									          asURI(xslt),
									          null,
									          CalabashWithPipelineModules.getModuleUriResolver(compileClassPath));
								} else {
									List sourceAsURI = new ArrayList();
									engine.run(asURI(HtmlizeSourcesMojo.class.getResource("/htmlize-sources/htmlize-xml.xpl")).toASCIIString(),
									           ImmutableMap.of("sources", (List)ImmutableList.of(asURI(f).toASCIIString())),
									           null,
									           ImmutableMap.of("input-base-uri", asURI(sourceDirectory).toASCIIString(),
									                           "output-base-uri", asURI(outputDirectory).toASCIIString()),
									           params);
								}
							}
						}
					}
				);
			}
			final Htmlizer fallbackHtmlizer = new Htmlizer() {
				public void run(Iterable sources, File sourceDirectory, File outputDirectory) throws XProcExecutionException {
					for (File f : sources) {
						try {
							File outputFile = new File(outputDirectory, relativize(asURI(sourceDirectory), asURI(f)) + "/index.md");
							outputFile.getParentFile().mkdirs();
							BufferedReader reader = new BufferedReader(new FileReader(f));
							BufferedWriter writer = new BufferedWriter(new FileWriter(outputFile));
							writer.write("");
							writer.newLine();
							writer.newLine();
							writer.write("~~~");
							writer.newLine();
							String line;
							while ((line = reader.readLine()) != null) {
								writer.write(line);
								writer.newLine(); }
							writer.write("~~~");
							writer.newLine();
							writer.close();
						} catch (Exception e) {
							throw new RuntimeException("Error processing file " + f, e);
						}
					}
				}
			};
			Multimap index = Multimaps.index(
				sources,
				new Function() {
					public Htmlizer apply(File f) {
						for (Map.Entry kv : htmlizers.entrySet())
							if (kv.getKey().accept(f.getParentFile(), f.getName()))
								return kv.getValue();
						return fallbackHtmlizer; }});
			outputDirectory.mkdirs();
			for (Map.Entry> kv : index.asMap().entrySet())
				kv.getKey().run(kv.getValue(), sourceDirectory, outputDirectory);
			
			// Generate directory index files
			List files = new ArrayList(); {
				for (String f : scanner.getIncludedFiles())
					files.add(f);
			}
			for (String dir : scanner.getIncludedDirectories()) {
				File outputFile = new File(outputDirectory, dir + "/index.md");
				outputFile.getParentFile().mkdirs();
				BufferedWriter writer = new BufferedWriter(new FileWriter(outputFile));
				writer.write("");
				writer.newLine();
				writer.newLine();
				int slash = dir.lastIndexOf('/');
				if (slash > 0) {
					String parent = dir.substring(0, slash);
					for (String d : scanner.getIncludedDirectories()) {
						if (parent.equals(d)) {
							writer.write("- [../](../)");
							writer.newLine();
							break;
						}
					}
				}
				for (String d : scanner.getIncludedDirectories()) {
					slash = d.lastIndexOf('/');
					if (dir.equals(slash < 0 ? "" : d.substring(0, slash))) {
						d = d.substring(slash + 1);
						writer.write("- [" + d + "/](" + d + ")");
						writer.newLine();
					}
				}
				for (Iterator i = files.iterator(); i.hasNext();) {
					String f = i.next();
					slash = f.lastIndexOf('/');
					if (dir.equals(slash < 0 ? "" : f.substring(0, slash))) {
						f = f.substring(slash + 1);
						writer.write("- [" + f + "](" + f + ")");
						writer.newLine();
						i.remove();
					}
				}
				writer.close();
			}
		} catch (Throwable e) {
			e.printStackTrace();
			throw new MojoFailureException(e.getMessage(), e);
		}
	}
	
	private static interface Htmlizer {
		public void run(Iterable files, File sourceDirectory, File outputDirectory);
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy