From f727c6dd1339c014cf0a91825ab2c21f0dded2d6 Mon Sep 17 00:00:00 2001 From: Florian Date: Sat, 29 Apr 2023 00:29:29 +0200 Subject: [PATCH] frontend 2.0: initial version - auto refresh function - light and dark theme - monaco editor (vscode) with "apex" as syntax highlighting language * apex seems to work quite fine (better than no highlighting) * future possibility: own plantuml language syntax support * future possibility: autocomplete (to much work but maybe partial) - implemented example for `!theme ...` - implemented example for `<&icon>` * future possibility: code validation - implemented example for `@start...` and `@end...`: * should be the first or last command * should be of the some type (e.g. `@startyaml` and @endyaml) * should be used exactly once per document/diagram - editor and preview is splitable into two windows like the "Extract window" functionality on (plantuml.com)[https://www.plantuml.com/plantuml] - multi index / multi paging diagram support - diagram can be displayed/rended as PNG, SVG, ASCII Art or PDF - Ctrl+s download the PlantUML Code as code file (diagram.puml) - Ctrl+, opens the settings and Esc closes the settings --- .editorconfig | 19 + .gitattributes | 1 + .vscode/settings.json | 8 +- pom.jdk8.xml | 34 +- pom.xml | 34 +- .../plantuml/servlet/PlantUmlServlet.java | 30 +- .../servlet/PlantUmlUIHelperServlet.java | 174 ++++ src/main/webapp/WEB-INF/web.xml | 483 +++++------ src/main/webapp/assets/copy.svg | 1 + src/main/webapp/assets/dock.svg | 1 + src/main/webapp/assets/file-types/ascii.svg | 1 + src/main/webapp/assets/file-types/map.svg | 1 + src/main/webapp/assets/file-types/pdf.svg | 1 + src/main/webapp/assets/file-types/png.svg | 1 + src/main/webapp/assets/file-types/svg.svg | 1 + src/main/webapp/assets/file-types/txt.svg | 1 + src/main/webapp/assets/github-fork-me.png | Bin 0 -> 6893 bytes src/main/webapp/assets/settings.svg | 1 + src/main/webapp/assets/undock.svg | 1 + src/main/webapp/footer.jspf | 4 - src/main/webapp/index.jsp | 128 ++- src/main/webapp/plantuml.css | 419 ++++++++-- src/main/webapp/plantuml.js | 761 +++++++++++++++++- src/main/webapp/plantumllanguage.js | 384 +++++++++ src/main/webapp/previewer.jsp | 26 + src/main/webapp/resource/footer.jsp | 1 + src/main/webapp/resource/githubribbon.html | 18 +- src/main/webapp/resource/htmlheadbase.jsp | 16 + src/main/webapp/resource/preview.jsp | 89 ++ src/main/webapp/resource/settings.jsp | 39 + ...socialbuttons2.jspf => socialbuttons2.jsp} | 0 .../plantuml/servlet/AllTests.java | 2 +- .../plantuml/servlet/TestAsciiArt.java | 3 + .../plantuml/servlet/TestAsciiCoder.java | 3 + .../plantuml/servlet/TestCharset.java | 2 + .../plantuml/servlet/TestCheck.java | 3 + .../plantuml/servlet/TestForm.java | 303 ------- .../plantuml/servlet/TestImage.java | 3 + .../plantuml/servlet/TestLanguage.java | 2 + .../sourceforge/plantuml/servlet/TestMap.java | 3 + .../sourceforge/plantuml/servlet/TestSVG.java | 3 + .../plantuml/servlet/TestWebUI.java | 209 +++++ .../servlet/utils/JUnitWebDriver.java | 79 ++ .../servlet/{ => utils}/TestUtils.java | 2 +- .../servlet/{ => utils}/WebappTestCase.java | 14 +- .../servlet/utils/WebappUITestCase.java | 90 +++ 46 files changed, 2638 insertions(+), 761 deletions(-) create mode 100644 .editorconfig create mode 100644 .gitattributes create mode 100644 src/main/java/net/sourceforge/plantuml/servlet/PlantUmlUIHelperServlet.java create mode 100644 src/main/webapp/assets/copy.svg create mode 100644 src/main/webapp/assets/dock.svg create mode 100644 src/main/webapp/assets/file-types/ascii.svg create mode 100644 src/main/webapp/assets/file-types/map.svg create mode 100644 src/main/webapp/assets/file-types/pdf.svg create mode 100644 src/main/webapp/assets/file-types/png.svg create mode 100644 src/main/webapp/assets/file-types/svg.svg create mode 100644 src/main/webapp/assets/file-types/txt.svg create mode 100644 src/main/webapp/assets/github-fork-me.png create mode 100644 src/main/webapp/assets/settings.svg create mode 100644 src/main/webapp/assets/undock.svg delete mode 100644 src/main/webapp/footer.jspf create mode 100644 src/main/webapp/plantumllanguage.js create mode 100644 src/main/webapp/previewer.jsp create mode 100644 src/main/webapp/resource/footer.jsp create mode 100644 src/main/webapp/resource/htmlheadbase.jsp create mode 100644 src/main/webapp/resource/preview.jsp create mode 100644 src/main/webapp/resource/settings.jsp rename src/main/webapp/resource/{socialbuttons2.jspf => socialbuttons2.jsp} (100%) delete mode 100644 src/test/java/net/sourceforge/plantuml/servlet/TestForm.java create mode 100644 src/test/java/net/sourceforge/plantuml/servlet/TestWebUI.java create mode 100644 src/test/java/net/sourceforge/plantuml/servlet/utils/JUnitWebDriver.java rename src/test/java/net/sourceforge/plantuml/servlet/{ => utils}/TestUtils.java (92%) rename src/test/java/net/sourceforge/plantuml/servlet/{ => utils}/WebappTestCase.java (88%) create mode 100644 src/test/java/net/sourceforge/plantuml/servlet/utils/WebappUITestCase.java diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..fc2c138 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,19 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +indent_style = space +indent_size = 2 +trim_trailing_whitespace = true + +[*.java] +indent_size = 4 + +[*.md] +max_line_length = off +trim_trailing_whitespace = false + +[*.puml] +insert_final_newline = false diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..6313b56 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* text=auto eol=lf diff --git a/.vscode/settings.json b/.vscode/settings.json index a78440a..691fda1 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -2,21 +2,23 @@ "java.configuration.updateBuildConfiguration": "automatic", "cSpell.words": [ "Arnaud", + "buildx", "ditaa", "endditaa", "enduml", "epstext", "etag", + "ghaction", "Lalloni", + "monaco", "plantuml", "Roques", "servlet", "servlets", "startditaa", "startuml", - "utxt", - "ghaction", - "buildx" + "undock", + "utxt" ], "cSpell.allowCompoundWords": true } \ No newline at end of file diff --git a/pom.jdk8.xml b/pom.jdk8.xml index 6a8c881..37c595d 100644 --- a/pom.jdk8.xml +++ b/pom.jdk8.xml @@ -56,7 +56,7 @@ 1.2023.6 11.0.7 - 5.63.0 + 0.36.1 1.2 @@ -71,7 +71,9 @@ 4.13.2 - 2.53.0 + 4.8.3 + 5.3.2 + 2.11.0 ${jetty.version} @@ -106,8 +108,8 @@ org.webjars.npm - codemirror - ${codemirror.version} + monaco-editor + ${monaco-editor.version} jakarta.servlet @@ -175,9 +177,21 @@ test - net.sourceforge.htmlunit - htmlunit - ${htmlunit.version} + org.seleniumhq.selenium + selenium-java + ${selenium.version} + test + + + io.github.bonigarcia + webdrivermanager + ${selenium-webdrivermanager.version} + test + + + commons-io + commons-io + ${commons-io.version} test @@ -365,9 +379,9 @@ org.webjars.npm - codemirror - ${codemirror.version} - **/lib/*.js,**/lib/*.css + monaco-editor + ${monaco-editor.version} + **/min/vs/loader.js,**/min/vs/**/*,**/min-maps/vs/**/* ${project.build.outputDirectory} diff --git a/pom.xml b/pom.xml index d961fd1..af2be3e 100644 --- a/pom.xml +++ b/pom.xml @@ -56,7 +56,7 @@ 1.2023.6 11.0.7 - 5.63.0 + 0.36.1 1.2 @@ -71,7 +71,9 @@ 4.13.2 - 2.53.0 + 4.8.3 + 5.3.2 + 2.11.0 ${jetty.version} @@ -106,8 +108,8 @@ org.webjars.npm - codemirror - ${codemirror.version} + monaco-editor + ${monaco-editor.version} org.eclipse.jetty @@ -153,9 +155,21 @@ test - net.sourceforge.htmlunit - htmlunit - ${htmlunit.version} + org.seleniumhq.selenium + selenium-java + ${selenium.version} + test + + + io.github.bonigarcia + webdrivermanager + ${selenium-webdrivermanager.version} + test + + + commons-io + commons-io + ${commons-io.version} test @@ -346,9 +360,9 @@ org.webjars.npm - codemirror - ${codemirror.version} - **/lib/*.js,**/lib/*.css + monaco-editor + ${monaco-editor.version} + **/min/vs/loader.js,**/min/vs/**/*,**/min-maps/vs/**/* ${project.build.outputDirectory} diff --git a/src/main/java/net/sourceforge/plantuml/servlet/PlantUmlServlet.java b/src/main/java/net/sourceforge/plantuml/servlet/PlantUmlServlet.java index 123067e..b744f3f 100644 --- a/src/main/java/net/sourceforge/plantuml/servlet/PlantUmlServlet.java +++ b/src/main/java/net/sourceforge/plantuml/servlet/PlantUmlServlet.java @@ -36,6 +36,7 @@ import jakarta.servlet.http.HttpServletResponse; import net.sourceforge.plantuml.OptionFlags; import net.sourceforge.plantuml.api.PlantumlUtils; +import net.sourceforge.plantuml.code.NoPlantumlCompressionException; import net.sourceforge.plantuml.png.MetadataTag; import net.sourceforge.plantuml.servlet.utility.Configuration; import net.sourceforge.plantuml.servlet.utility.UmlExtractor; @@ -134,8 +135,15 @@ public class PlantUmlServlet extends AsciiCoderServlet { final int idx = UrlDataExtractor.getIndex(request.getRequestURI()); // forward to index.jsp + final String path; + final String view = request.getParameter("view"); + if (view != null && view.equalsIgnoreCase("previewer")) { + path = "/previewer.jsp"; + } else { + path = "/index.jsp"; + } prepareRequestForDispatch(request, text, idx); - final RequestDispatcher dispatcher = request.getRequestDispatcher("/index.jsp"); + final RequestDispatcher dispatcher = request.getRequestDispatcher(path); dispatcher.forward(request, response); } @@ -183,6 +191,10 @@ public class PlantUmlServlet extends AsciiCoderServlet { if (text != null && !text.isEmpty()) { return text; } + } catch (NoPlantumlCompressionException e) { + // no textual diagram source available from Url + // ignore and try 2. method (metadata) below + // do not spam output console } catch (Exception e) { e.printStackTrace(); } @@ -229,26 +241,16 @@ public class PlantUmlServlet extends AsciiCoderServlet { */ private void prepareRequestForDispatch(HttpServletRequest request, String text, int idx) throws IOException { final String encoded = getTranscoder().encode(text); - final String index = (idx < 0) ? "" : idx + "/"; // diagram sources + request.setAttribute("encoded", encoded); request.setAttribute("decoded", text); - request.setAttribute("index", idx); + request.setAttribute("index", (idx < 0) ? "" : idx); // properties request.setAttribute("showSocialButtons", Configuration.get("SHOW_SOCIAL_BUTTONS")); request.setAttribute("showGithubRibbon", Configuration.get("SHOW_GITHUB_RIBBON")); - // image URLs - final boolean hasImg = !text.isEmpty(); - request.setAttribute("hasImg", hasImg); - request.setAttribute("imgurl", "png/" + index + encoded); - request.setAttribute("svgurl", "svg/" + index + encoded); - request.setAttribute("pdfurl", "pdf/" + index + encoded); - request.setAttribute("txturl", "txt/" + index + encoded); - request.setAttribute("mapurl", "map/" + index + encoded); // map for diagram source if necessary - final boolean hasMap = PlantumlUtils.hasCMapData(text); - request.setAttribute("hasMap", hasMap); String map = ""; - if (hasMap) { + if (PlantumlUtils.hasCMapData(text)) { try { map = UmlExtractor.extractMap(text); } catch (Exception e) { diff --git a/src/main/java/net/sourceforge/plantuml/servlet/PlantUmlUIHelperServlet.java b/src/main/java/net/sourceforge/plantuml/servlet/PlantUmlUIHelperServlet.java new file mode 100644 index 0000000..d3bc5be --- /dev/null +++ b/src/main/java/net/sourceforge/plantuml/servlet/PlantUmlUIHelperServlet.java @@ -0,0 +1,174 @@ +/* ======================================================================== + * PlantUML : a free UML diagram generator + * ======================================================================== + * + * Project Info: https://plantuml.com + * + * This file is part of PlantUML. + * + * PlantUML is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * PlantUML distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ +package net.sourceforge.plantuml.servlet; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.StringWriter; +import java.io.Writer; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.stream.Collectors; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +import net.sourceforge.plantuml.theme.ThemeUtils; +import net.sourceforge.plantuml.openiconic.data.DummyIcon; + +import org.w3c.dom.Document; +import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; + +/** + * Small PlantUML frontend or UI helper. + */ +@SuppressWarnings("SERIAL") +public class PlantUmlUIHelperServlet extends HttpServlet { + + private interface HelperConsumer { + void accept(HttpServletRequest request, HttpServletResponse response) throws IOException; + } + + private final Map helpers = new HashMap<>(); + private String svgIconsSpriteCache = null; + + public PlantUmlUIHelperServlet() { + // add all supported request items/helper methods + helpers.put("icons.svg", this::sendIconsSprite); + helpers.put("icons", this::sendIcons); + helpers.put("themes", this::sendThemes); + } + + @Override + public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + request.setCharacterEncoding("UTF-8"); + + final String requestItem = request.getParameter("request"); + final HelperConsumer requestHelper = this.helpers.get(requestItem); + String errorMsg = null; + if (requestItem == null) { + errorMsg = "Request item not set."; + } else if (requestHelper == null) { + errorMsg = "Unknown requested item: " + requestItem; + } + if (errorMsg != null) { + response.addHeader("Access-Control-Allow-Origin", "*"); + response.setContentType("text/plain;charset=UTF-8"); + response.getWriter().write(errorMsg); + response.setStatus(HttpServletResponse.SC_BAD_REQUEST); + return; + } + + requestHelper.accept(request, response); + } + + private String toJson(List list) { + return "[" + list.stream() + .map(item -> "\"" + item.replace("\"", "\\\"") + "\"") + .collect(Collectors.joining(",")) + "]"; + } + + private void sendJson(HttpServletResponse response, String json) throws IOException { + response.addHeader("Access-Control-Allow-Origin", "*"); + response.setContentType("application/json;charset=UTF-8"); + response.getWriter().write(json); + } + + private List getIcons() throws IOException { + InputStream in = DummyIcon.class.getResourceAsStream("all.txt"); + try (BufferedReader br = new BufferedReader(new InputStreamReader(in))) { + return br.lines().collect(Collectors.toList()); + } + } + + private void sendIconsSprite(HttpServletRequest request, HttpServletResponse response) throws IOException { + if (svgIconsSpriteCache == null) { + // NOTE: all icons has the following svg tag attributes: width="8" height="8" viewBox="0 0 8 8" + List iconNames = getIcons(); + StringBuilder sprite = new StringBuilder(); + sprite.append("\n"); + sprite.append("\n"); + sprite.append(" \n"); + sprite.append("\n"); + for (String name : iconNames) { + try (InputStream in = DummyIcon.class.getResourceAsStream(name + ".svg")) { + DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + Document doc = db.parse(in); + Writer out = new StringWriter(); + out.write(""); + + Transformer tf = TransformerFactory.newInstance().newTransformer(); + tf.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); + tf.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); + tf.setOutputProperty(OutputKeys.INDENT, "no"); + NodeList svgInnerNodes = doc.getElementsByTagName("svg").item(0).getChildNodes(); + for (int index = 0; index < svgInnerNodes.getLength(); index++) { + tf.transform(new DOMSource(svgInnerNodes.item(index)), new StreamResult(out)); + } + + out.write(""); + sprite.append(out.toString() + "\n"); + } catch (ParserConfigurationException | SAXException | TransformerException ex) { + // skip icons which can not be parsed/read + Logger logger = Logger.getLogger("com.plantuml"); + logger.log(Level.WARNING, "SVG icon '{0}' could not be parsed. Skip!", name); + } + } + sprite.append("\n"); + svgIconsSpriteCache = sprite.toString(); + } + response.addHeader("Access-Control-Allow-Origin", "*"); + response.setContentType("image/svg+xml;charset=UTF-8"); + response.getWriter().write(svgIconsSpriteCache); + } + + private void sendIcons(HttpServletRequest request, HttpServletResponse response) throws IOException { + sendJson(response, toJson(getIcons())); + } + + private void sendThemes(HttpServletRequest request, HttpServletResponse response) throws IOException { + sendJson(response, toJson(ThemeUtils.getAllThemeNames())); + } +} diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml index 9d5ea77..bb69e2f 100644 --- a/src/main/webapp/WEB-INF/web.xml +++ b/src/main/webapp/WEB-INF/web.xml @@ -1,237 +1,246 @@ - - - - - - - - - PlantUML - PlantUML Online Server - - - - - - - 120 - - - - - - - - - - - - - - - - - - - org.eclipse.jetty.servlet.Default.welcomeServlets - exact - - - - - - - - - jsp - org.eclipse.jetty.jsp.JettyJspServlet - - compilerSourceVM - 1.7 - - - compilerTargetVM - 1.7 - - - - - plantumlservlet - net.sourceforge.plantuml.servlet.PlantUmlServlet - - - plantumlservlet - /welcome - - - plantumlservlet - /uml/* - - - plantumlservlet - /form - - - plantumlservlet - /start/* - - - - imgservlet - net.sourceforge.plantuml.servlet.ImgServlet - - - imgservlet - /png/* - - - imgservlet - /img/* - - - - svgservlet - net.sourceforge.plantuml.servlet.SvgServlet - - - svgservlet - /svg/* - - - - pdfservlet - net.sourceforge.plantuml.servlet.PdfServlet - - - pdfservlet - /pdf/* - - - - epsservlet - net.sourceforge.plantuml.servlet.EpsServlet - - - epsservlet - /eps/* - - - - epstextservlet - net.sourceforge.plantuml.servlet.EpsTextServlet - - - epstextservlet - /epstext/* - - - - base64servlet - net.sourceforge.plantuml.servlet.Base64Servlet - - - base64servlet - /base64/* - - - - asciiservlet - net.sourceforge.plantuml.servlet.AsciiServlet - - - asciiservlet - /txt/* - - - - proxyservlet - net.sourceforge.plantuml.servlet.ProxyServlet - - - proxyservlet - /proxy - - - - oldproxyservlet - net.sourceforge.plantuml.servlet.OldProxyServlet - - - oldproxyservlet - /proxy/* - - - - mapservlet - net.sourceforge.plantuml.servlet.MapServlet - - - mapservlet - /map/* - - - - checkservlet - net.sourceforge.plantuml.servlet.CheckSyntaxServlet - - - checkservlet - /check/* - - - - languageservlet - net.sourceforge.plantuml.servlet.LanguageServlet - - - languageservlet - /language - - - - asciicoder - net.sourceforge.plantuml.servlet.AsciiCoderServlet - - - asciicoder - /coder/* - - - - - - - - - java.lang.Throwable - /error.jsp - - - - 500 - /error.jsp - - - - - - - - - welcome - - - + + + + + + + + + PlantUML + PlantUML Online Server + + + + + + + 120 + + + + + + + + + + + + + + + + + + + org.eclipse.jetty.servlet.Default.welcomeServlets + exact + + + + + + + + + jsp + org.eclipse.jetty.jsp.JettyJspServlet + + compilerSourceVM + 1.8 + + + compilerTargetVM + 1.8 + + + + + plantumlservlet + net.sourceforge.plantuml.servlet.PlantUmlServlet + + + plantumlservlet + /welcome + + + plantumlservlet + /uml/* + + + plantumlservlet + /form + + + plantumlservlet + /start/* + + + + imgservlet + net.sourceforge.plantuml.servlet.ImgServlet + + + imgservlet + /png/* + + + imgservlet + /img/* + + + + svgservlet + net.sourceforge.plantuml.servlet.SvgServlet + + + svgservlet + /svg/* + + + + pdfservlet + net.sourceforge.plantuml.servlet.PdfServlet + + + pdfservlet + /pdf/* + + + + epsservlet + net.sourceforge.plantuml.servlet.EpsServlet + + + epsservlet + /eps/* + + + + epstextservlet + net.sourceforge.plantuml.servlet.EpsTextServlet + + + epstextservlet + /epstext/* + + + + base64servlet + net.sourceforge.plantuml.servlet.Base64Servlet + + + base64servlet + /base64/* + + + + asciiservlet + net.sourceforge.plantuml.servlet.AsciiServlet + + + asciiservlet + /txt/* + + + + proxyservlet + net.sourceforge.plantuml.servlet.ProxyServlet + + + proxyservlet + /proxy + + + + oldproxyservlet + net.sourceforge.plantuml.servlet.OldProxyServlet + + + oldproxyservlet + /proxy/* + + + + mapservlet + net.sourceforge.plantuml.servlet.MapServlet + + + mapservlet + /map/* + + + + checkservlet + net.sourceforge.plantuml.servlet.CheckSyntaxServlet + + + checkservlet + /check/* + + + + languageservlet + net.sourceforge.plantuml.servlet.LanguageServlet + + + languageservlet + /language + + + + asciicoderservlet + net.sourceforge.plantuml.servlet.AsciiCoderServlet + + + asciicoderservlet + /coder/* + + + + plantumluihelperservlet + net.sourceforge.plantuml.servlet.PlantUmlUIHelperServlet + + + plantumluihelperservlet + /ui-helper/* + + + + + + + + + java.lang.Throwable + /error.jsp + + + + 500 + /error.jsp + + + + + + + + + welcome + + + diff --git a/src/main/webapp/assets/copy.svg b/src/main/webapp/assets/copy.svg new file mode 100644 index 0000000..17e128a --- /dev/null +++ b/src/main/webapp/assets/copy.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/main/webapp/assets/dock.svg b/src/main/webapp/assets/dock.svg new file mode 100644 index 0000000..bc4aa2e --- /dev/null +++ b/src/main/webapp/assets/dock.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/main/webapp/assets/file-types/ascii.svg b/src/main/webapp/assets/file-types/ascii.svg new file mode 100644 index 0000000..801b93d --- /dev/null +++ b/src/main/webapp/assets/file-types/ascii.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/main/webapp/assets/file-types/map.svg b/src/main/webapp/assets/file-types/map.svg new file mode 100644 index 0000000..edd9b8a --- /dev/null +++ b/src/main/webapp/assets/file-types/map.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/main/webapp/assets/file-types/pdf.svg b/src/main/webapp/assets/file-types/pdf.svg new file mode 100644 index 0000000..e718679 --- /dev/null +++ b/src/main/webapp/assets/file-types/pdf.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/main/webapp/assets/file-types/png.svg b/src/main/webapp/assets/file-types/png.svg new file mode 100644 index 0000000..1553a22 --- /dev/null +++ b/src/main/webapp/assets/file-types/png.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/main/webapp/assets/file-types/svg.svg b/src/main/webapp/assets/file-types/svg.svg new file mode 100644 index 0000000..7d2670d --- /dev/null +++ b/src/main/webapp/assets/file-types/svg.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/main/webapp/assets/file-types/txt.svg b/src/main/webapp/assets/file-types/txt.svg new file mode 100644 index 0000000..4623344 --- /dev/null +++ b/src/main/webapp/assets/file-types/txt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/main/webapp/assets/github-fork-me.png b/src/main/webapp/assets/github-fork-me.png new file mode 100644 index 0000000000000000000000000000000000000000..10c08f4d5502ad12ba372eb80812df4bdd557a57 GIT binary patch literal 6893 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

os+m<8wB|BFG%0_DlNxb zA02$&PvP#V_D!y06B8z{QwQC?A;l6W_XXi_h7vyOV$lFQ#7Kl zU>?X!>Qj&qiXZRZV}N_(r656qhA83hoNA9lN}lmHNEY5)c!2n=X=V1c`wIs0l0(l2 z1Q$7&(P*P&r!y91EDopdb^J8c2RqBRFfNhC7mL!27fGcrfIFG2e=1Fg(|&axSGr;~ zTa#VBpje?w<4;ZZWXF$XKYChEr_-9og<`Q%(!wL|mCc z8TwX+5=|;46AE6__=S~N>^wuskDJx-cNrb96lw`DhEU*!#};`Qmhb?`;IN;OE2H1@l3vl z9@47DTYd0Ov-Gkuwy+0o?n}%bZW_R#Z?|b0G8k150BD80sF5M7lZCOxZ`*;oVAMQb zpc~Wos(6Zl6gy{-sIC%V8c#Hbo&wi>V(`YOaB>n!p=e~eC=Hcp;4ZAQ1(*gz3EQWo zr&pBn2^Bb0YWl~rnz5qu4Pfhx9bU%S7&K`;XriPo@jn^2A?}hY_g;f~SvrUcxokT4 z>@x~#nZ`i5%#ic>%Tz3u(8>GVH!ZMwrAFSW-y zxen)7aYiOjNJsy>okruN`Z4n2%*_Fcf(4VxYSU@bEI?G@Av&oVUAw$-y1(|Wlc8+ti#G@P4 zeTSP1sI)6!tA0S@O;u%9r{1C6vq1T0j67iod*kVp>8~RcXyxR(hTi7SPtAZ0-k6~S{;Sg-!u8X#y7Amdd1 zpA(|{bA>I9r%hz}>R&bU=ix@4S)f Stw#EP1<=tl)U1ZvWBv~ks^vBS literal 0 HcmV?d00001 diff --git a/src/main/webapp/assets/settings.svg b/src/main/webapp/assets/settings.svg new file mode 100644 index 0000000..7362425 --- /dev/null +++ b/src/main/webapp/assets/settings.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/main/webapp/assets/undock.svg b/src/main/webapp/assets/undock.svg new file mode 100644 index 0000000..89d2bbb --- /dev/null +++ b/src/main/webapp/assets/undock.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/main/webapp/footer.jspf b/src/main/webapp/footer.jspf deleted file mode 100644 index 509d089..0000000 --- a/src/main/webapp/footer.jspf +++ /dev/null @@ -1,4 +0,0 @@ -

diff --git a/src/main/webapp/index.jsp b/src/main/webapp/index.jsp index 4da6ec8..265c90a 100644 --- a/src/main/webapp/index.jsp +++ b/src/main/webapp/index.jsp @@ -1,93 +1,57 @@ <%@ page info="index" contentType="text/html; charset=utf-8" pageEncoding="utf-8" session="false" %> - <% - // diagram sources - String decoded = request.getAttribute("decoded").toString(); - // properties - boolean showSocialButtons = (boolean)request.getAttribute("showSocialButtons"); - boolean showGithubRibbon = (boolean)request.getAttribute("showGithubRibbon"); - // image URLs - boolean hasImg = (boolean)request.getAttribute("hasImg"); - String imgurl = request.getAttribute("imgurl").toString(); - String svgurl = request.getAttribute("svgurl").toString(); - String txturl = request.getAttribute("txturl").toString(); - String pdfurl = request.getAttribute("pdfurl").toString(); - String mapurl = request.getAttribute("mapurl").toString(); - // map for diagram source if necessary - boolean hasMap = (boolean)request.getAttribute("hasMap"); - String map = request.getAttribute("map").toString(); + // diagram sources + String encoded = request.getAttribute("encoded").toString(); + String decoded = request.getAttribute("decoded").toString(); + String index = request.getAttribute("index").toString(); + String diagramUrl = ((index.isEmpty()) ? "" : index + "/") + encoded; + // map for diagram source if necessary + String map = request.getAttribute("map").toString(); + boolean hasMap = !map.isEmpty(); + // properties + boolean showSocialButtons = (boolean)request.getAttribute("showSocialButtons"); + boolean showGithubRibbon = (boolean)request.getAttribute("showGithubRibbon"); %> - + - - - - - - - - - - - - PlantUMLServer + <%@ include file="resource/htmlheadbase.jsp" %> + PlantUML Server -