package folioxml.export.plugins; import folioxml.config.*; import folioxml.core.InvalidMarkupException; import folioxml.core.TokenUtils; import folioxml.export.FileNode; import folioxml.export.InfobaseSetPlugin; import folioxml.export.LogStreamProvider; import folioxml.slx.ISlxTokenReader; import folioxml.slx.SlxRecord; import folioxml.xml.Node; import folioxml.xml.XmlRecord; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.net.URI; import java.nio.file.FileAlreadyExistsException; import java.nio.file.Path; import java.util.ArrayList; import java.util.List; public class ExportHtmlFiles implements InfobaseSetPlugin { public ExportHtmlFiles() { } public ExportHtmlFiles(boolean addNavLinks, boolean useHighslide) { this.addNavLinks = addNavLinks; this.useHighslide = useHighslide; } Boolean useHighslide = null; Boolean addNavLinks = null; protected OutputStreamWriter out; private ExportLocations export; @Override public void beginInfobaseSet(InfobaseSet set, ExportLocations export, LogStreamProvider logs) throws IOException, InvalidMarkupException { this.export = export; if (useHighslide == null) useHighslide = set.getBool("use_highslide"); if (useHighslide == null) useHighslide = true; if (addNavLinks == null) addNavLinks = set.getBool("add_nav_links"); if (addNavLinks == null) addNavLinks = true; } @Override public void beginInfobase(InfobaseConfig infobase) throws IOException { } @Override public ISlxTokenReader wrapSlxReader(ISlxTokenReader reader) { return reader; } @Override public void onSlxRecordParsed(SlxRecord clean_slx) throws InvalidMarkupException, IOException { } @Override public void onRecordTransformed(XmlRecord xr, SlxRecord dirty_slx) throws InvalidMarkupException, IOException { } @Override public FileNode assignFileNode(XmlRecord xr, SlxRecord dirty_slx) throws InvalidMarkupException, IOException { return null; } FileNode lastFile = null; @Override public void onRecordComplete(XmlRecord xr, FileNode file) throws InvalidMarkupException, IOException { if (lastFile != file) { if (lastFile != null && out != null) { //New URI String newUri = export.getUri(file.getRelativePath(), AssetType.Html, export.getLocalPath(lastFile.getRelativePath(), AssetType.Html, FolderCreation.None)); writeNextLink(newUri, file); closeFile(); } openFile(file, xr); if (lastFile != null) { String previousUrl = export.getUri(lastFile.getRelativePath(), AssetType.Html, export.getLocalPath(file.getRelativePath(), AssetType.Html, FolderCreation.None)); writePrevLink(previousUrl, lastFile); } lastFile = file; } //Let's not write the root record, mkay? if (!xr.isRootRecord()) out.write(xr.toXmlString(false)); } @Override public void endInfobase(InfobaseConfig infobase) throws IOException, InvalidMarkupException { } @Override public void endInfobaseSet(InfobaseSet set) throws IOException, InvalidMarkupException { closeFile(); } private void openFile(FileNode fn, XmlRecord xr) throws IOException { XmlRecord root = xr.getRoot(); if (out != null) throw new IOException(); //Invalid state List<String> cssUris = new ArrayList<String>(); List<String> jsUris = new ArrayList<String>(); String filename = fn.getRelativePath(); Path htmlPath = export.getLocalPath(filename, AssetType.Html, FolderCreation.CreateParents); if (htmlPath.toFile().exists()) throw new FileAlreadyExistsException(htmlPath.toString()); cssUris.add(export.getUri("foliostyle.css", AssetType.Css, htmlPath)); //Add highslide javascript/css String highslideFolder = export.getUri("highslide/", AssetType.Javascript, htmlPath) + "/"; if (useHighslide) { jsUris.add(URI.create(highslideFolder).resolve("highslide-with-html.js").toString()); cssUris.add(URI.create(highslideFolder).resolve("highslide.css").toString()); } out = new OutputStreamWriter(new FileOutputStream(htmlPath.toFile()), "UTF8"); out.append("<!DOCTYPE html>\n"); openElement("html"); openElement("head"); writeIndent(); out.append("<meta charset=\"utf-8\" />\n"); openElement("title"); String title = fn.getAttributes().get("heading"); if (title == null) title = ""; out.write(TokenUtils.lightEntityEncode(title)); closeElement("title"); if (fn.getBag().get("folio-id") != null) { writeIndent(); out.append("<meta data-first-folio-id=\"" + fn.getBag().get("folio-id").toString() + "\" />\n"); } if (fn.getBag().get("folio-level") != null) { writeIndent(); out.append("<meta data-folio-level=\"" + fn.getBag().get("folio-level").toString() + "\" />\n"); } writeIndent(); for (String uri : cssUris) out.append("<link rel='stylesheet' type='text/css' href='" + uri + "' />\n"); for (String uri : jsUris) out.append("<script type='text/javascript' src='" + uri + "'></script>\n"); if (useHighslide) out.append("<script type=\"text/javascript\">hs.graphicsDir = '" + URI.create(highslideFolder).resolve("graphics") + "/';</script>\n"); closeElement("head"); openElement("body"); } private void closeFile() throws IOException { closeElement("body"); closeElement("html"); out.close(); out = null; } private boolean indentXml = true; private int indentLevel = 0; private String indentString = " "; private void writeIndent() throws IOException { for (int i = 0; i < indentLevel; i++) { out.append(indentString); } } private void openElement(String elementName) throws IOException { writeIndent(); out.append("<"); out.append(elementName); out.append(">\n"); indentLevel++; } private void openElement(Node element) throws IOException { StringBuilder sb = new StringBuilder(); writeIndent(); element.writeTokenTo(sb); out.append(sb); out.append("\n"); indentLevel++; } private void closeElement(String elementName) throws IOException { indentLevel--; writeIndent(); out.append("</"); out.append(elementName); out.append(">\n"); } private void writeLink(String uri, String text) throws IOException, InvalidMarkupException { Node a = new Node("<a>" + TokenUtils.lightEntityEncode(text) + "</a>"); a.setTagName("a"); a.addClass("folio_pagination_link"); a.set("href", uri); out.write(a.toXmlString(false)); } private void writeNextLink(String uri, FileNode target) throws IOException, InvalidMarkupException { writeLink(uri, "Next: " + target.getAttributes().get("heading")); } private void writePrevLink(String uri, FileNode target) throws IOException, InvalidMarkupException { writeLink(uri, "Prev: " + target.getAttributes().get("heading")); } }