]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/markdown/html/HtmlDocumentationGeneration.java
e92f4d3b4a62e94d497cab50b188c9afc1dba7f3
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / markdown / html / HtmlDocumentationGeneration.java
1 package org.simantics.scl.compiler.markdown.html;
2
3 import java.io.IOException;
4 import java.io.InputStream;
5 import java.io.StringReader;
6 import java.nio.charset.Charset;
7 import java.util.Arrays;
8 import java.util.List;
9
10 import org.simantics.scl.compiler.errors.Failable;
11 import org.simantics.scl.compiler.markdown.internal.MarkdownParser;
12 import org.simantics.scl.compiler.markdown.nodes.HeaderNode;
13 import org.simantics.scl.compiler.markdown.nodes.Node;
14 import org.simantics.scl.compiler.module.Module;
15 import org.simantics.scl.compiler.module.repository.ModuleRepository;
16
17 public class HtmlDocumentationGeneration {
18     
19     private static String STYLESHEET;
20     static {
21         try {
22             InputStream stream = HtmlDocumentationGeneration.class.getResourceAsStream("SclDoc.css");
23             try {
24                 byte[] buffer = new byte[2048];
25                 int pos = 0;
26                 while(true) {
27                     int count = stream.read(buffer, pos, buffer.length-pos);
28                     if(count <= 0)
29                         break;
30                     pos += count;
31                     if(pos == buffer.length)
32                         buffer = Arrays.copyOf(buffer, 2*buffer.length);
33                 }
34                 STYLESHEET = new String(buffer, Charset.forName("UTF-8"));
35             } finally {
36                 stream.close();
37             }
38         } catch(IOException e) {
39             e.printStackTrace();
40         }
41     }
42     
43     public static String generate(ModuleRepository moduleRepository, String documentationName, String navigation) {
44         String documentation = moduleRepository.getDocumentation(documentationName);
45         if(documentation == null || documentation.isEmpty()) {
46             Failable<Module> module = moduleRepository.getModule(documentationName);
47             if(!module.didSucceed())
48                 return "Didn't find documentation or module for " + documentationName + ".";
49             documentation = "# Module "+documentationName+"\n\nThis module is undocumented. This is a list of its definitions.\n\n::undocumented[]";
50         }
51         MarkdownParser parser = new MarkdownParser();
52         try {
53             Node result = parser.parseDocument(new StringReader(documentation));
54             result.processExtensionNodes(new SCLDocumentationExtensionNodeHandler(moduleRepository, documentationName));
55             
56             StringBuilder b = new StringBuilder();
57             addHTMLHeader(b);
58
59             if(navigation != null) {
60                 b.append("<table class=\"pagestructure\"><tr><td class=\"navi\">\n");
61                 b.append(navigation);
62                 b.append("</td><td class=\"content\">\n");
63             }
64             addContentsTree(b, result);
65             result.toHtml(b);
66             if(navigation != null)
67                 b.append("</td></tr></table>\n");
68             
69             addHTMLFooter(b);
70             
71             return b.toString();
72         } catch (IOException e) {
73             e.printStackTrace();
74             return "";
75         }
76     }
77     
78     private static void addContentsTree(StringBuilder b, Node node) {
79         List<HeaderNode> headers = node.extractHeaders();
80         if(headers.size() > 1) {
81             int minLevel=Integer.MAX_VALUE, minLevelCount=0;
82             for(HeaderNode header : headers) {
83                 if(header.level == minLevel)
84                     ++minLevelCount;
85                 else if(header.level < minLevel) {
86                     minLevel = header.level;
87                     minLevelCount = 1;
88                 }
89             }
90             if(minLevelCount == 1)
91                 ++minLevel;
92             
93             b.append("<div id=\"contentspanel\">");
94             b.append("<h2>Contents</h2>\n");
95             int level = minLevel-1;
96             for(HeaderNode header : headers) {
97                 if(header.level < minLevel)
98                     continue;
99                 while(header.level != level) {
100                     if(header.level > level) {
101                         b.append("<ul>\n");
102                         ++level;
103                     }
104                     else {
105                         b.append("</ul>\n");
106                         --level;
107                     }
108                 }
109                  
110                 b.append("<li><a href=\"#");
111                 header.toPlainText(b);
112                 b.append("\">");
113                 header.toPlainText(b);
114                 b.append("</a></li>\n");
115             }
116             while(level >= minLevel) {
117                 b.append("</ul>\n");
118                 --level;
119             }
120             b.append("</div>");
121         }
122     }
123
124     private static void addHTMLHeader(StringBuilder b) {
125         b.append("<!DOCTYPE html>\n");
126         b.append("<html>\n");
127         b.append("<head>\n");
128         b.append("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n");
129         b.append("<meta http-equiv=\"x-ua-compatible\" content=\"IE=Edge\" />\n");
130         /*b.append("<script type=\"text/javascript\"\n");
131         b.append("  src=\"https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML\">\n");
132         b.append("</script>\n");*/
133         b.append("<style type=\"text/css\">\n");
134         b.append(STYLESHEET);
135         b.append("</style>\n");
136         b.append("</head>\n");
137         b.append("<body>\n");
138     }
139     
140     private static void addHTMLFooter(StringBuilder b) {
141         b.append("</body>\n");
142         b.append("</html>\n");
143     }
144 }