--- /dev/null
+package org.simantics.scl.compiler.internal.parsing.documentation;\r
+\r
+import java.io.IOException;\r
+import java.io.StringReader;\r
+import java.util.regex.Matcher;\r
+import java.util.regex.Pattern;\r
+\r
+import org.simantics.scl.compiler.elaboration.modules.Documentation;\r
+import org.simantics.scl.compiler.types.Type;\r
+import org.simantics.scl.compiler.types.util.TypeUnparsingContext;\r
+\r
+public abstract class HtmlUnparsingContext {\r
+ StringBuilder stringBuilder;\r
+ String listLevel = "";\r
+ \r
+ int tableOfContentsLevel = 0;\r
+ StringBuilder tableOfContents;\r
+ \r
+ int headerLinkId = 0;\r
+ \r
+ public HtmlUnparsingContext(StringBuilder stringBuilder) {\r
+ this.stringBuilder = stringBuilder;\r
+ this.tableOfContents = null;\r
+ }\r
+ \r
+ public HtmlUnparsingContext() {\r
+ this(new StringBuilder());\r
+ tableOfContents = new StringBuilder();\r
+ }\r
+\r
+ public StringBuilder getStringBuilder() {\r
+ return stringBuilder;\r
+ }\r
+ \r
+ public StringBuilder getTableOfContents() {\r
+ return tableOfContents;\r
+ }\r
+ \r
+ public void finishTableOfContents() {\r
+ while(tableOfContentsLevel > 0) {\r
+ tableOfContents.append("</ul>\n");\r
+ --tableOfContentsLevel;\r
+ }\r
+ }\r
+ \r
+ public void header(int level, String text) {\r
+ clear(); \r
+ ++headerLinkId;\r
+ stringBuilder.append("<h").append(level)\r
+ .append(" id=\"sec").append(headerLinkId).append("\">")\r
+ .append(text)\r
+ .append("</h").append(level).append(">\n");\r
+ \r
+ while(tableOfContentsLevel > level) {\r
+ tableOfContents.append("</ul>\n");\r
+ --tableOfContentsLevel;\r
+ }\r
+ while(tableOfContentsLevel < level) {\r
+ tableOfContents.append("<ul>\n");\r
+ ++tableOfContentsLevel;\r
+ }\r
+ tableOfContents.append("<li><a href=\"#sec")\r
+ .append(headerLinkId).append("\">")\r
+ .append(text).append("</a></li>\n");\r
+ }\r
+ \r
+ public void clear() {\r
+ setListLevel("");\r
+ }\r
+ \r
+ public void setListLevel(String newLevel) {\r
+ String oldLevel = this.listLevel;\r
+ int commonLevel = 0;\r
+ while(commonLevel < oldLevel.length() && commonLevel < newLevel.length() && \r
+ newLevel.charAt(commonLevel) == oldLevel.charAt(commonLevel))\r
+ ++commonLevel;\r
+ \r
+ for(int i=oldLevel.length()-1;i>=commonLevel;--i) {\r
+ char c = oldLevel.charAt(i);\r
+ if(c == '*')\r
+ stringBuilder.append("</ul>\n");\r
+ else if(c == '#')\r
+ stringBuilder.append("</ol>\n");\r
+ }\r
+ for(int i=commonLevel;i<newLevel.length();++i) {\r
+ char c = newLevel.charAt(i);\r
+ if(c == '*')\r
+ stringBuilder.append("<ul>\n");\r
+ else if(c == '#')\r
+ stringBuilder.append("<ol>\n");\r
+ }\r
+ \r
+ this.listLevel = newLevel;\r
+ }\r
+ \r
+ public void appendDocumentation(String doc) {\r
+ DocumentationLexer lexer = new DocumentationLexer(new StringReader(doc));\r
+\r
+ clear();\r
+ while(true) {\r
+ DocumentationElement element = null;\r
+ try {\r
+ element = lexer.nextToken();\r
+ } catch (IOException e) {\r
+ e.printStackTrace();\r
+ } catch (DocumentationParsingException e) {\r
+ e.printStackTrace();\r
+ }\r
+ if(element == null)\r
+ break;\r
+ element.toHtml(this);\r
+ }\r
+ clear();\r
+ }\r
+\r
+ public static String escape(String text) {\r
+ return text.replace("&", "&").replace("<", "<").replace(">", ">");\r
+ }\r
+\r
+ public abstract void documentEntity(String ref);\r
+\r
+ public void appendType(TypeUnparsingContext tuc, Type type, int precedence) {\r
+ StringBuilder b = new StringBuilder();\r
+ type.toString(tuc, b, precedence);\r
+ stringBuilder.append(escape(b.toString()));\r
+ }\r
+ \r
+ public void appendType(TypeUnparsingContext tuc, Type type) {\r
+ appendType(tuc, type, 3);\r
+ }\r
+ \r
+ public void appendRef(String ref) {\r
+ stringBuilder.append("<a name=\"").append(ref).append("\" class=\"ref\">")\r
+ .append(escape(ref)).append("</a>");\r
+ }\r
+\r
+ public Documentation toDocumentation() {\r
+ finishTableOfContents();\r
+ return new Documentation(stringBuilder.toString(), tableOfContents.toString());\r
+ }\r
+\r
+ private static final Pattern PARAGRAPH_PATTERN = Pattern.compile("'[^ ']+'|@[^@]+@");\r
+ \r
+ public void appendParagraph(String text) {\r
+ clear();\r
+ stringBuilder.append("<p>"); \r
+ Matcher m = PARAGRAPH_PATTERN.matcher(text);\r
+ int lastAppend = 0;\r
+ while(m.find()) {\r
+ int start = m.start();\r
+ int end = m.end();\r
+ \r
+ stringBuilder.append(text, lastAppend, start);\r
+ char c = text.charAt(start);\r
+ if(c == '\'') {\r
+ String ref = text.substring(start+1, end-1);\r
+ \r
+ stringBuilder.append("<code><a href=\"#").append(ref).append("\">")\r
+ .append(ref)\r
+ .append("</a></code>");\r
+ }\r
+ else if(c == '@') {\r
+ stringBuilder.append("<code>").append(text, start+1, end-1).append("</code>");\r
+ }\r
+ lastAppend = end;\r
+ }\r
+ stringBuilder.append(text, lastAppend, text.length());\r
+ stringBuilder.append("</p>\n"); \r
+ }\r
+}\r