+package org.simantics.scl.compiler.markdown.html;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringReader;
+import java.nio.charset.Charset;
+import java.util.Arrays;
+import java.util.List;
+
+import org.simantics.scl.compiler.errors.Failable;
+import org.simantics.scl.compiler.markdown.internal.MarkdownParser;
+import org.simantics.scl.compiler.markdown.nodes.HeaderNode;
+import org.simantics.scl.compiler.markdown.nodes.Node;
+import org.simantics.scl.compiler.module.Module;
+import org.simantics.scl.compiler.module.repository.ModuleRepository;
+
+public class HtmlDocumentationGeneration {
+
+ private static String STYLESHEET;
+ static {
+ try {
+ InputStream stream = HtmlDocumentationGeneration.class.getResourceAsStream("SclDoc.css");
+ try {
+ byte[] buffer = new byte[2048];
+ int pos = 0;
+ while(true) {
+ int count = stream.read(buffer, pos, buffer.length-pos);
+ if(count <= 0)
+ break;
+ pos += count;
+ if(pos == buffer.length)
+ buffer = Arrays.copyOf(buffer, 2*buffer.length);
+ }
+ STYLESHEET = new String(buffer, Charset.forName("UTF-8"));
+ } finally {
+ stream.close();
+ }
+ } catch(IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public static String generate(ModuleRepository moduleRepository, String documentationName, String navigation) {
+ String documentation = moduleRepository.getDocumentation(documentationName);
+ if(documentation == null || documentation.isEmpty()) {
+ Failable<Module> module = moduleRepository.getModule(documentationName);
+ if(!module.didSucceed())
+ return "Didn't find documentation or module for " + documentationName + ".";
+ documentation = "# Module "+documentationName+"\n\nThis module is undocumented. This is a list of its definitions.\n\n::undocumented[]";
+ }
+ MarkdownParser parser = new MarkdownParser();
+ try {
+ Node result = parser.parseDocument(new StringReader(documentation));
+ result.processExtensionNodes(new SCLDocumentationExtensionNodeHandler(moduleRepository, documentationName));
+
+ StringBuilder b = new StringBuilder();
+ addHTMLHeader(b);
+
+ if(navigation != null) {
+ b.append("<table class=\"pagestructure\"><tr><td class=\"navi\">\n");
+ b.append(navigation);
+ b.append("</td><td class=\"content\">\n");
+ }
+ addContentsTree(b, result);
+ result.toHtml(b);
+ if(navigation != null)
+ b.append("</td></tr></table>\n");
+
+ addHTMLFooter(b);
+
+ return b.toString();
+ } catch (IOException e) {
+ e.printStackTrace();
+ return "";
+ }
+ }
+
+ private static void addContentsTree(StringBuilder b, Node node) {
+ List<HeaderNode> headers = node.extractHeaders();
+ if(headers.size() > 1) {
+ int minLevel=Integer.MAX_VALUE, minLevelCount=0;
+ for(HeaderNode header : headers) {
+ if(header.level == minLevel)
+ ++minLevelCount;
+ else if(header.level < minLevel) {
+ minLevel = header.level;
+ minLevelCount = 1;
+ }
+ }
+ if(minLevelCount == 1)
+ ++minLevel;
+
+ b.append("<div id=\"contentspanel\">");
+ b.append("<h2>Contents</h2>\n");
+ int level = minLevel-1;
+ for(HeaderNode header : headers) {
+ if(header.level < minLevel)
+ continue;
+ while(header.level != level) {
+ if(header.level > level) {
+ b.append("<ul>\n");
+ ++level;
+ }
+ else {
+ b.append("</ul>\n");
+ --level;
+ }
+ }
+
+ b.append("<li><a href=\"#");
+ header.toPlainText(b);
+ b.append("\">");
+ header.toPlainText(b);
+ b.append("</a></li>\n");
+ }
+ while(level >= minLevel) {
+ b.append("</ul>\n");
+ --level;
+ }
+ b.append("</div>");
+ }
+ }
+
+ private static void addHTMLHeader(StringBuilder b) {
+ b.append("<!DOCTYPE html>\n");
+ b.append("<html>\n");
+ b.append("<head>\n");
+ b.append("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n");
+ b.append("<meta http-equiv=\"x-ua-compatible\" content=\"IE=Edge\" />\n");
+ /*b.append("<script type=\"text/javascript\"\n");
+ b.append(" src=\"https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML\">\n");
+ b.append("</script>\n");*/
+ b.append("<style type=\"text/css\">\n");
+ b.append(STYLESHEET);
+ b.append("</style>\n");
+ b.append("</head>\n");
+ b.append("<body>\n");
+ }
+
+ private static void addHTMLFooter(StringBuilder b) {
+ b.append("</body>\n");
+ b.append("</html>\n");
+ }
+}