1
0
mirror of https://github.com/octoleo/plantuml-server.git synced 2024-10-04 09:43:03 +00:00

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
This commit is contained in:
Florian 2023-04-29 00:29:29 +02:00 committed by PlantUML
parent 763976abdd
commit f727c6dd13
46 changed files with 2638 additions and 761 deletions

19
.editorconfig Normal file
View File

@ -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

1
.gitattributes vendored Normal file
View File

@ -0,0 +1 @@
* text=auto eol=lf

View File

@ -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
}

View File

@ -56,7 +56,7 @@
<plantuml.version>1.2023.6</plantuml.version>
<!-- Please keep the jetty version identical with the docker image -->
<jetty.version>11.0.7</jetty.version>
<codemirror.version>5.63.0</codemirror.version>
<monaco-editor.version>0.36.1</monaco-editor.version>
<!-- dependencies -->
<jstl.version>1.2</jstl.version>
@ -71,7 +71,9 @@
<!-- Testing -->
<junit.version>4.13.2</junit.version>
<htmlunit.version>2.53.0</htmlunit.version>
<selenium.version>4.8.3</selenium.version>
<selenium-webdrivermanager.version>5.3.2</selenium-webdrivermanager.version>
<commons-io.version>2.11.0</commons-io.version>
<jetty-server.version>${jetty.version}</jetty-server.version>
<!-- build plugin management -->
@ -106,8 +108,8 @@
</dependency>
<dependency>
<groupId>org.webjars.npm</groupId>
<artifactId>codemirror</artifactId>
<version>${codemirror.version}</version>
<artifactId>monaco-editor</artifactId>
<version>${monaco-editor.version}</version>
</dependency>
<dependency>
<groupId>jakarta.servlet</groupId>
@ -175,9 +177,21 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>net.sourceforge.htmlunit</groupId>
<artifactId>htmlunit</artifactId>
<version>${htmlunit.version}</version>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>${selenium.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.github.bonigarcia</groupId>
<artifactId>webdrivermanager</artifactId>
<version>${selenium-webdrivermanager.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>${commons-io.version}</version>
<scope>test</scope>
</dependency>
<dependency>
@ -365,9 +379,9 @@
<artifactItems>
<artifactItem>
<groupId>org.webjars.npm</groupId>
<artifactId>codemirror</artifactId>
<version>${codemirror.version}</version>
<includes>**/lib/*.js,**/lib/*.css</includes>
<artifactId>monaco-editor</artifactId>
<version>${monaco-editor.version}</version>
<includes>**/min/vs/loader.js,**/min/vs/**/*,**/min-maps/vs/**/*</includes>
<outputDirectory>${project.build.outputDirectory}</outputDirectory>
</artifactItem>
</artifactItems>

34
pom.xml
View File

@ -56,7 +56,7 @@
<plantuml.version>1.2023.6</plantuml.version>
<!-- Please keep the jetty version identical with the docker image -->
<jetty.version>11.0.7</jetty.version>
<codemirror.version>5.63.0</codemirror.version>
<monaco-editor.version>0.36.1</monaco-editor.version>
<!-- dependencies -->
<jstl.version>1.2</jstl.version>
@ -71,7 +71,9 @@
<!-- Testing -->
<junit.version>4.13.2</junit.version>
<htmlunit.version>2.53.0</htmlunit.version>
<selenium.version>4.8.3</selenium.version>
<selenium-webdrivermanager.version>5.3.2</selenium-webdrivermanager.version>
<commons-io.version>2.11.0</commons-io.version>
<jetty-server.version>${jetty.version}</jetty-server.version>
<!-- build plugin management -->
@ -106,8 +108,8 @@
</dependency>
<dependency>
<groupId>org.webjars.npm</groupId>
<artifactId>codemirror</artifactId>
<version>${codemirror.version}</version>
<artifactId>monaco-editor</artifactId>
<version>${monaco-editor.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
@ -153,9 +155,21 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>net.sourceforge.htmlunit</groupId>
<artifactId>htmlunit</artifactId>
<version>${htmlunit.version}</version>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>${selenium.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.github.bonigarcia</groupId>
<artifactId>webdrivermanager</artifactId>
<version>${selenium-webdrivermanager.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>${commons-io.version}</version>
<scope>test</scope>
</dependency>
<dependency>
@ -346,9 +360,9 @@
<artifactItems>
<artifactItem>
<groupId>org.webjars.npm</groupId>
<artifactId>codemirror</artifactId>
<version>${codemirror.version}</version>
<includes>**/lib/*.js,**/lib/*.css</includes>
<artifactId>monaco-editor</artifactId>
<version>${monaco-editor.version}</version>
<includes>**/min/vs/loader.js,**/min/vs/**/*,**/min-maps/vs/**/*</includes>
<outputDirectory>${project.build.outputDirectory}</outputDirectory>
</artifactItem>
</artifactItems>

View File

@ -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) {

View File

@ -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<String, HelperConsumer> 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<String> 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<String> 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<String> iconNames = getIcons();
StringBuilder sprite = new StringBuilder();
sprite.append("<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"8\" height=\"8\" viewBox=\"0 0 8 8\">\n");
sprite.append("<defs>\n");
sprite.append(" <style><![CDATA[\n");
sprite.append(" .sprite { display: none; }\n");
sprite.append(" .sprite:target { display: inline; }\n");
sprite.append(" ]]></style>\n");
sprite.append("</defs>\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("<g class=\"sprite\" id=\"" + name + "\">");
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("</g>");
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("</svg>\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()));
}
}

View File

@ -1,237 +1,246 @@
<?xml version="1.0" encoding="UTF-8"?>
<web-app
xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xmlns:web="https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
version="5.0"
>
<!-- ========================================================== -->
<!-- General -->
<!-- ========================================================== -->
<!-- Name the application -->
<display-name>PlantUML</display-name>
<description>PlantUML Online Server</description>
<!-- This app is cluster-ready -->
<distributable />
<!-- Set timeout to 120 minutes -->
<session-config>
<session-timeout>120</session-timeout>
</session-config>
<!-- ========================================================== -->
<!-- Custom Tag Libraries -->
<!-- ========================================================== -->
<!-- Taglib declarations are no longer required since JSP 2.0, see Removing taglib from web.xml -->
<!-- The <taglib> did not need to be a child of <jsp-config> in earlier versions but is required as of Tomcat 7 -->
<!-- Note that you can only have one <jsp-config> element per web.xml -->
<!--
<jsp-config>
<taglib>
<taglib-uri>http://java.sun.com/jsp/jstl/core</taglib-uri>
<taglib-location>/WEB-INF/lib/c.tld</taglib-location>
</taglib>
</jsp-config>
-->
<!-- ========================================================== -->
<!-- Context Parameters -->
<!-- ========================================================== -->
<context-param>
<param-name>org.eclipse.jetty.servlet.Default.welcomeServlets</param-name>
<param-value>exact</param-value>
</context-param>
<!-- ========================================================== -->
<!-- Servlets -->
<!-- ========================================================== -->
<servlet>
<servlet-name>jsp</servlet-name>
<servlet-class>org.eclipse.jetty.jsp.JettyJspServlet</servlet-class>
<init-param>
<param-name>compilerSourceVM</param-name>
<param-value>1.7</param-value>
</init-param>
<init-param>
<param-name>compilerTargetVM</param-name>
<param-value>1.7</param-value>
</init-param>
</servlet>
<servlet>
<servlet-name>plantumlservlet</servlet-name>
<servlet-class>net.sourceforge.plantuml.servlet.PlantUmlServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>plantumlservlet</servlet-name>
<url-pattern>/welcome</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>plantumlservlet</servlet-name>
<url-pattern>/uml/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>plantumlservlet</servlet-name>
<url-pattern>/form</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>plantumlservlet</servlet-name>
<url-pattern>/start/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>imgservlet</servlet-name>
<servlet-class>net.sourceforge.plantuml.servlet.ImgServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>imgservlet</servlet-name>
<url-pattern>/png/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>imgservlet</servlet-name>
<url-pattern>/img/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>svgservlet</servlet-name>
<servlet-class>net.sourceforge.plantuml.servlet.SvgServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>svgservlet</servlet-name>
<url-pattern>/svg/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>pdfservlet</servlet-name>
<servlet-class>net.sourceforge.plantuml.servlet.PdfServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>pdfservlet</servlet-name>
<url-pattern>/pdf/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>epsservlet</servlet-name>
<servlet-class>net.sourceforge.plantuml.servlet.EpsServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>epsservlet</servlet-name>
<url-pattern>/eps/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>epstextservlet</servlet-name>
<servlet-class>net.sourceforge.plantuml.servlet.EpsTextServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>epstextservlet</servlet-name>
<url-pattern>/epstext/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>base64servlet</servlet-name>
<servlet-class>net.sourceforge.plantuml.servlet.Base64Servlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>base64servlet</servlet-name>
<url-pattern>/base64/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>asciiservlet</servlet-name>
<servlet-class>net.sourceforge.plantuml.servlet.AsciiServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>asciiservlet</servlet-name>
<url-pattern>/txt/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>proxyservlet</servlet-name>
<servlet-class>net.sourceforge.plantuml.servlet.ProxyServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>proxyservlet</servlet-name>
<url-pattern>/proxy</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>oldproxyservlet</servlet-name>
<servlet-class>net.sourceforge.plantuml.servlet.OldProxyServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>oldproxyservlet</servlet-name>
<url-pattern>/proxy/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>mapservlet</servlet-name>
<servlet-class>net.sourceforge.plantuml.servlet.MapServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>mapservlet</servlet-name>
<url-pattern>/map/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>checkservlet</servlet-name>
<servlet-class>net.sourceforge.plantuml.servlet.CheckSyntaxServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>checkservlet</servlet-name>
<url-pattern>/check/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>languageservlet</servlet-name>
<servlet-class>net.sourceforge.plantuml.servlet.LanguageServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>languageservlet</servlet-name>
<url-pattern>/language</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>asciicoder</servlet-name>
<servlet-class>net.sourceforge.plantuml.servlet.AsciiCoderServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>asciicoder</servlet-name>
<url-pattern>/coder/*</url-pattern>
</servlet-mapping>
<!-- ========================================================== -->
<!-- Error Handler -->
<!-- ========================================================== -->
<error-page>
<exception-type>java.lang.Throwable</exception-type>
<location>/error.jsp</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/error.jsp</location>
</error-page>
<!-- ========================================================== -->
<!-- Welcome Files -->
<!-- ========================================================== -->
<welcome-file-list>
<welcome-file>welcome</welcome-file>
</welcome-file-list>
</web-app>
<?xml version="1.0" encoding="UTF-8"?>
<web-app
xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xmlns:web="https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
version="5.0"
>
<!-- ========================================================== -->
<!-- General -->
<!-- ========================================================== -->
<!-- Name the application -->
<display-name>PlantUML</display-name>
<description>PlantUML Online Server</description>
<!-- This app is cluster-ready -->
<distributable />
<!-- Set timeout to 120 minutes -->
<session-config>
<session-timeout>120</session-timeout>
</session-config>
<!-- ========================================================== -->
<!-- Custom Tag Libraries -->
<!-- ========================================================== -->
<!-- Taglib declarations are no longer required since JSP 2.0, see Removing taglib from web.xml -->
<!-- The <taglib> did not need to be a child of <jsp-config> in earlier versions but is required as of Tomcat 7 -->
<!-- Note that you can only have one <jsp-config> element per web.xml -->
<!--
<jsp-config>
<taglib>
<taglib-uri>http://java.sun.com/jsp/jstl/core</taglib-uri>
<taglib-location>/WEB-INF/lib/c.tld</taglib-location>
</taglib>
</jsp-config>
-->
<!-- ========================================================== -->
<!-- Context Parameters -->
<!-- ========================================================== -->
<context-param>
<param-name>org.eclipse.jetty.servlet.Default.welcomeServlets</param-name>
<param-value>exact</param-value>
</context-param>
<!-- ========================================================== -->
<!-- Servlets -->
<!-- ========================================================== -->
<servlet>
<servlet-name>jsp</servlet-name>
<servlet-class>org.eclipse.jetty.jsp.JettyJspServlet</servlet-class>
<init-param>
<param-name>compilerSourceVM</param-name>
<param-value>1.8</param-value>
</init-param>
<init-param>
<param-name>compilerTargetVM</param-name>
<param-value>1.8</param-value>
</init-param>
</servlet>
<servlet>
<servlet-name>plantumlservlet</servlet-name>
<servlet-class>net.sourceforge.plantuml.servlet.PlantUmlServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>plantumlservlet</servlet-name>
<url-pattern>/welcome</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>plantumlservlet</servlet-name>
<url-pattern>/uml/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>plantumlservlet</servlet-name>
<url-pattern>/form</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>plantumlservlet</servlet-name>
<url-pattern>/start/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>imgservlet</servlet-name>
<servlet-class>net.sourceforge.plantuml.servlet.ImgServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>imgservlet</servlet-name>
<url-pattern>/png/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>imgservlet</servlet-name>
<url-pattern>/img/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>svgservlet</servlet-name>
<servlet-class>net.sourceforge.plantuml.servlet.SvgServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>svgservlet</servlet-name>
<url-pattern>/svg/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>pdfservlet</servlet-name>
<servlet-class>net.sourceforge.plantuml.servlet.PdfServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>pdfservlet</servlet-name>
<url-pattern>/pdf/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>epsservlet</servlet-name>
<servlet-class>net.sourceforge.plantuml.servlet.EpsServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>epsservlet</servlet-name>
<url-pattern>/eps/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>epstextservlet</servlet-name>
<servlet-class>net.sourceforge.plantuml.servlet.EpsTextServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>epstextservlet</servlet-name>
<url-pattern>/epstext/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>base64servlet</servlet-name>
<servlet-class>net.sourceforge.plantuml.servlet.Base64Servlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>base64servlet</servlet-name>
<url-pattern>/base64/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>asciiservlet</servlet-name>
<servlet-class>net.sourceforge.plantuml.servlet.AsciiServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>asciiservlet</servlet-name>
<url-pattern>/txt/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>proxyservlet</servlet-name>
<servlet-class>net.sourceforge.plantuml.servlet.ProxyServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>proxyservlet</servlet-name>
<url-pattern>/proxy</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>oldproxyservlet</servlet-name>
<servlet-class>net.sourceforge.plantuml.servlet.OldProxyServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>oldproxyservlet</servlet-name>
<url-pattern>/proxy/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>mapservlet</servlet-name>
<servlet-class>net.sourceforge.plantuml.servlet.MapServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>mapservlet</servlet-name>
<url-pattern>/map/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>checkservlet</servlet-name>
<servlet-class>net.sourceforge.plantuml.servlet.CheckSyntaxServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>checkservlet</servlet-name>
<url-pattern>/check/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>languageservlet</servlet-name>
<servlet-class>net.sourceforge.plantuml.servlet.LanguageServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>languageservlet</servlet-name>
<url-pattern>/language</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>asciicoderservlet</servlet-name>
<servlet-class>net.sourceforge.plantuml.servlet.AsciiCoderServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>asciicoderservlet</servlet-name>
<url-pattern>/coder/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>plantumluihelperservlet</servlet-name>
<servlet-class>net.sourceforge.plantuml.servlet.PlantUmlUIHelperServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>plantumluihelperservlet</servlet-name>
<url-pattern>/ui-helper/*</url-pattern>
</servlet-mapping>
<!-- ========================================================== -->
<!-- Error Handler -->
<!-- ========================================================== -->
<error-page>
<exception-type>java.lang.Throwable</exception-type>
<location>/error.jsp</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/error.jsp</location>
</error-page>
<!-- ========================================================== -->
<!-- Welcome Files -->
<!-- ========================================================== -->
<welcome-file-list>
<welcome-file>welcome</welcome-file>
</welcome-file-list>
</web-app>

View File

@ -0,0 +1 @@
<svg height="24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M16 16v4c0 1.152-.848 2-2 2H4c-1.152 0-2-.848-2-2V10c0-1.152.848-2 2-2h4V4c0-1.152.848-2 2-2h10c1.152 0 2 .848 2 2v10c0 1.152-.848 2-2 2h-4zm-2 0h-4c-1.152 0-2-.848-2-2v-4H4v10h10v-4zM10 4v10h10V4H10z" fill-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 301 B

View File

@ -0,0 +1 @@
<svg height="512" width="512" xmlns="http://www.w3.org/2000/svg"><path d="M384 224v184a40 40 0 01-40 40H104a40 40 0 01-40-40V168a40 40 0 0140-40h167.48" fill="none" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="32"/><path fill="none" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="32" d="M216 184v112h112m-104-8L440 72"/></svg>

After

Width:  |  Height:  |  Size: 384 B

View File

@ -0,0 +1 @@
<svg class="bi bi-filetype-ascii" fill="currentColor" height="16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="M14 4.5V11h-1V4.5h-2A1.5 1.5 0 019.5 3V1H4a1 1 0 00-1 1v9H2V2a2 2 0 012-2h5.5zM2.404 14.903l-.313 1.028h-.8l1.342-3.999h.926l1.335 4h-.84l-.314-1.03H2.404zm1.178-.59l-.49-1.616h-.034l-.49 1.617h1.014zm1.782.977a1.178 1.178 0 01-.111-.449h.764a.58.58 0 00.255.384c.07.049.154.087.25.114.095.028.2.041.319.041.164 0 .3-.023.413-.07a.558.558 0 00.255-.193.507.507 0 00.085-.29.387.387 0 00-.153-.326c-.101-.08-.256-.144-.463-.193l-.618-.143a1.72 1.72 0 01-.54-.214 1.002 1.002 0 01-.35-.367 1.068 1.068 0 01-.123-.524c0-.244.063-.457.19-.639.127-.181.303-.322.527-.422.225-.1.484-.149.777-.149.304 0 .564.05.779.152.217.102.384.239.5.41.12.17.186.359.2.566h-.75a.56.56 0 00-.12-.258.623.623 0 00-.246-.181.923.923 0 00-.37-.068c-.216 0-.387.05-.512.152a.472.472 0 00-.184.384c0 .121.047.22.143.3a.97.97 0 00.404.175l.62.143c.218.05.407.12.567.211.16.09.285.21.375.358.09.148.135.335.135.56 0 .247-.063.466-.188.656-.133.196-.32.348-.54.439-.233.105-.52.158-.857.158a2.191 2.191 0 01-.665-.09 1.404 1.404 0 01-.478-.252 1.131 1.131 0 01-.29-.375zm4.383-2.246a1.732 1.732 0 00-.103.633v.495c0 .246.035.455.103.627a.834.834 0 00.299.393c.142.09.308.136.477.13a.872.872 0 00.402-.087.699.699 0 00.272-.248.8.8 0 00.117-.364h.765v.076c-.01.241-.088.475-.226.674-.136.194-.32.345-.55.454a1.81 1.81 0 01-.785.164c-.36 0-.665-.072-.915-.216a1.424 1.424 0 01-.57-.627c-.13-.272-.194-.597-.194-.976v-.498c0-.38.065-.705.196-.978.13-.274.32-.485.57-.633.253-.15.557-.223.913-.223.218 0 .42.032.606.097.187.062.35.153.49.272.283.241.452.591.465.964v.073h-.765a.85.85 0 00-.12-.38.7.7 0 00-.272-.261.802.802 0 00-.4-.097.814.814 0 00-.473.138.868.868 0 00-.302.398zm3.628-1.106v4h-.79v-4h.79zm1.337.005v3.999h-.791v-4h.79z" fill-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -0,0 +1 @@
<svg class="bi bi-filetype-map" fill="currentColor" height="16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="M14 4.5V14a2 2 0 01-2 2v-1a1 1 0 001-1V4.5h-2A1.5 1.5 0 019.5 3V1H4a1 1 0 00-1 1v9H2V2a2 2 0 012-2h5.5zM.706 15.849v-2.66h.038l.952 2.16h.516l.946-2.16h.038v2.66h.715V11.85h-.8l-1.14 2.596h-.026L.805 11.85H0v3.999zm7.31-3.999h1.6c.289 0 .533.06.732.179.201.117.355.276.46.477.106.201.158.427.158.677 0 .25-.053.476-.16.677-.106.199-.26.357-.464.474a1.46 1.46 0 01-.732.173h-.803v1.342h-.79V11.85zm2.06 1.714a.795.795 0 00.085-.381c0-.226-.062-.4-.185-.521-.123-.122-.294-.182-.513-.182h-.659v1.406h.66a.794.794 0 00.374-.082.574.574 0 00.238-.24zm-5.12 2.306l.313-1.028h1.336l.314 1.028h.84l-1.336-3.999h-.925l-1.329 3.96m1.79-3.195l.488 1.617H5.433l.49-1.617z" fill-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 808 B

View File

@ -0,0 +1 @@
<svg class="bi bi-filetype-pdf" fill="currentColor" height="16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="M14 4.5V14a2 2 0 01-2 2h-1v-1h1a1 1 0 001-1V4.5h-2A1.5 1.5 0 019.5 3V1H4a1 1 0 00-1 1v9H2V2a2 2 0 012-2h5.5L14 4.5zM1.6 11.85H0v3.999h.791v-1.342h.803c.287 0 .531-.057.732-.173.203-.117.358-.275.463-.474a1.42 1.42 0 00.161-.677c0-.25-.053-.476-.158-.677a1.176 1.176 0 00-.46-.477c-.2-.12-.443-.179-.732-.179zm.545 1.333a.795.795 0 01-.085.38.574.574 0 01-.238.241.794.794 0 01-.375.082H.788V12.48h.66c.218 0 .389.06.512.181.123.122.185.296.185.522zm1.217-1.333v3.999h1.46c.401 0 .734-.08.998-.237a1.45 1.45 0 00.595-.689c.13-.3.196-.662.196-1.084 0-.42-.065-.778-.196-1.075a1.426 1.426 0 00-.589-.68c-.264-.156-.599-.234-1.005-.234H3.362zm.791.645h.563c.248 0 .45.05.609.152a.89.89 0 01.354.454c.079.201.118.452.118.753a2.3 2.3 0 01-.068.592 1.14 1.14 0 01-.196.422.8.8 0 01-.334.252 1.298 1.298 0 01-.483.082h-.563v-2.707zm3.743 1.763v1.591h-.79V11.85h2.548v.653H7.896v1.117h1.606v.638H7.896z" fill-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -0,0 +1 @@
<svg class="bi bi-filetype-png" fill="currentColor" height="16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="M14 4.5V14a2 2 0 01-2 2v-1a1 1 0 001-1V4.5h-2A1.5 1.5 0 019.5 3V1H4a1 1 0 00-1 1v9H2V2a2 2 0 012-2h5.5L14 4.5zm-3.76 8.132c.076.153.123.317.14.492h-.776a.797.797 0 00-.097-.249.689.689 0 00-.17-.19.707.707 0 00-.237-.126.96.96 0 00-.299-.044c-.285 0-.506.1-.665.302-.156.201-.234.484-.234.85v.498c0 .234.032.439.097.615a.881.881 0 00.304.413.87.87 0 00.519.146.967.967 0 00.457-.096.67.67 0 00.272-.264c.06-.11.091-.23.091-.363v-.255H8.82v-.59h1.576v.798c0 .193-.032.377-.097.55a1.29 1.29 0 01-.293.458 1.37 1.37 0 01-.495.313c-.197.074-.43.111-.697.111a1.98 1.98 0 01-.753-.132 1.447 1.447 0 01-.533-.377 1.58 1.58 0 01-.32-.58 2.482 2.482 0 01-.105-.745v-.506c0-.362.067-.678.2-.95.134-.271.328-.482.582-.633.256-.152.565-.228.926-.228.238 0 .45.033.636.1.187.066.348.158.48.275.133.117.238.253.314.407zm-8.64-.706H0v4h.791v-1.343h.803c.287 0 .531-.057.732-.172.203-.118.358-.276.463-.475a1.42 1.42 0 00.161-.677c0-.25-.053-.475-.158-.677a1.176 1.176 0 00-.46-.477c-.2-.12-.443-.179-.732-.179zm.545 1.333a.795.795 0 01-.085.381.574.574 0 01-.238.24.794.794 0 01-.375.082H.788v-1.406h.66c.218 0 .389.06.512.182.123.12.185.295.185.521zm1.964 2.666V13.25h.032l1.761 2.675h.656v-3.999h-.75v2.66h-.032l-1.752-2.66h-.662v4h.747z" fill-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -0,0 +1 @@
<svg class="bi bi-filetype-svg" fill="currentColor" height="16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="M14 4.5V14a2 2 0 01-2 2v-1a1 1 0 001-1V4.5h-2A1.5 1.5 0 019.5 3V1H4a1 1 0 00-1 1v9H2V2a2 2 0 012-2h5.5L14 4.5zM0 14.841a1.13 1.13 0 00.401.823c.13.108.288.192.478.252.19.061.411.091.665.091.338 0 .624-.053.858-.158.237-.105.416-.252.54-.44a1.17 1.17 0 00.187-.656c0-.224-.045-.41-.135-.56a1 1 0 00-.375-.357 2.027 2.027 0 00-.565-.21l-.621-.144a.97.97 0 01-.405-.176.37.37 0 01-.143-.299c0-.156.061-.284.184-.384.125-.101.296-.152.513-.152.143 0 .266.023.37.068a.625.625 0 01.245.181.56.56 0 01.12.258h.75a1.092 1.092 0 00-.199-.566 1.21 1.21 0 00-.5-.41 1.813 1.813 0 00-.78-.152c-.293 0-.552.05-.776.15-.225.099-.4.24-.528.421-.127.182-.19.395-.19.639 0 .201.04.376.123.524.082.149.199.27.351.367.153.095.332.167.54.213l.618.144c.207.049.36.113.462.193a.387.387 0 01.153.326.512.512 0 01-.085.29.559.559 0 01-.256.193c-.111.047-.249.07-.413.07-.117 0-.224-.013-.32-.04a.837.837 0 01-.248-.115.578.578 0 01-.255-.384H0zm4.575 1.09h.952l1.327-3.999h-.879l-.887 3.138H5.05l-.897-3.138h-.917l1.339 4zm5.483-3.293c.076.152.123.316.14.492h-.776a.797.797 0 00-.096-.249.689.689 0 00-.17-.19.707.707 0 00-.237-.126.963.963 0 00-.3-.044c-.284 0-.506.1-.664.302-.157.2-.235.484-.235.85v.497c0 .235.033.44.097.616a.881.881 0 00.305.413.87.87 0 00.518.146.965.965 0 00.457-.097.67.67 0 00.273-.263c.06-.11.09-.23.09-.364v-.254h-.823v-.59h1.576v.798c0 .193-.032.377-.096.55a1.29 1.29 0 01-.293.457 1.37 1.37 0 01-.495.314c-.198.074-.43.111-.698.111a1.98 1.98 0 01-.752-.132 1.447 1.447 0 01-.534-.377 1.58 1.58 0 01-.319-.58 2.482 2.482 0 01-.105-.745v-.507c0-.36.066-.677.199-.949.134-.271.329-.482.583-.633.256-.152.564-.228.926-.228.238 0 .45.033.635.1.188.066.348.158.48.275.134.117.238.253.314.407z" fill-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -0,0 +1 @@
<svg class="bi bi-filetype-txt" fill="currentColor" height="16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="M14 4.5V14a2 2 0 01-2 2h-2v-1h2a1 1 0 001-1V4.5h-2A1.5 1.5 0 019.5 3V1H4a1 1 0 00-1 1v9H2V2a2 2 0 012-2h5.5L14 4.5zM1.928 15.849v-3.337h1.136v-.662H0v.662h1.134v3.337h.794zm4.689-3.999h-.894L4.9 13.289h-.035l-.832-1.439h-.932l1.228 1.983-1.24 2.016h.862l.853-1.415h.035l.85 1.415h.907l-1.253-1.992 1.274-2.007zm1.93.662v3.337h-.794v-3.337H6.619v-.662h3.064v.662H8.546z" fill-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 516 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

View File

@ -0,0 +1 @@
<svg height="512" width="512" xmlns="http://www.w3.org/2000/svg"><path d="M262.29 192.31a64 64 0 1057.4 57.4 64.13 64.13 0 00-57.4-57.4zM416.39 256a154.34 154.34 0 01-1.53 20.79l45.21 35.46a10.81 10.81 0 012.45 13.75l-42.77 74a10.81 10.81 0 01-13.14 4.59l-44.9-18.08a16.11 16.11 0 00-15.17 1.75A164.48 164.48 0 01325 400.8a15.94 15.94 0 00-8.82 12.14l-6.73 47.89a11.08 11.08 0 01-10.68 9.17h-85.54a11.11 11.11 0 01-10.69-8.87l-6.72-47.82a16.07 16.07 0 00-9-12.22 155.3 155.3 0 01-21.46-12.57 16 16 0 00-15.11-1.71l-44.89 18.07a10.81 10.81 0 01-13.14-4.58l-42.77-74a10.8 10.8 0 012.45-13.75l38.21-30a16.05 16.05 0 006-14.08c-.36-4.17-.58-8.33-.58-12.5s.21-8.27.58-12.35a16 16 0 00-6.07-13.94l-38.19-30A10.81 10.81 0 0149.48 186l42.77-74a10.81 10.81 0 0113.14-4.59l44.9 18.08a16.11 16.11 0 0015.17-1.75A164.48 164.48 0 01187 111.2a15.94 15.94 0 008.82-12.14l6.73-47.89A11.08 11.08 0 01213.23 42h85.54a11.11 11.11 0 0110.69 8.87l6.72 47.82a16.07 16.07 0 009 12.22 155.3 155.3 0 0121.46 12.57 16 16 0 0015.11 1.71l44.89-18.07a10.81 10.81 0 0113.14 4.58l42.77 74a10.8 10.8 0 01-2.45 13.75l-38.21 30a16.05 16.05 0 00-6.05 14.08c.33 4.14.55 8.3.55 12.47z" fill="none" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="32"/></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1 @@
<svg height="512" width="512" xmlns="http://www.w3.org/2000/svg"><path d="M384 224v184a40 40 0 01-40 40H104a40 40 0 01-40-40V168a40 40 0 0140-40h167.48M336 64h112v112M224 288L440 72" fill="none" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="32"/></svg>

After

Width:  |  Height:  |  Size: 281 B

View File

@ -1,4 +0,0 @@
<div id="footer">
<p>PlantUML Server Version <%= net.sourceforge.plantuml.version.Version.version() %>
</p>
</div>

View File

@ -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");
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<base href="<%= request.getContextPath() %>/" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="expires" content="0" />
<meta http-equiv="pragma" content="no-cache" />
<meta http-equiv="cache-control" content="no-cache, must-revalidate" />
<link rel="icon" href="favicon.ico" type="image/x-icon"/>
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon"/>
<link rel="stylesheet" href="plantuml.css" />
<link rel="stylesheet" href="webjars/codemirror/5.63.0/lib/codemirror.css" />
<script src="plantuml.js"></script>
<script src="webjars/codemirror/5.63.0/lib/codemirror.js"></script>
<title>PlantUMLServer</title>
<%@ include file="resource/htmlheadbase.jsp" %>
<title>PlantUML Server</title>
</head>
<body>
<div id="header">
<%-- PAGE TITLE --%>
<h1>PlantUML Server</h1>
<% if (showSocialButtons) { %>
<%@ include file="resource/socialbuttons1.html" %>
<% } %>
<% if (showGithubRibbon) { %>
<%@ include file="resource/githubribbon.html" %>
<% } %>
<p>Create your <a href="https://plantuml.com">PlantUML</a> diagrams directly in your browser!</p>
<div class="app flex-rows">
<div class="header">
<h1>PlantUML Server</h1>
<% if (showSocialButtons) { %>
<%@ include file="resource/socialbuttons1.html" %>
<% } %>
<% if (showGithubRibbon) { %>
<%@ include file="resource/githubribbon.html" %>
<% } %>
<p>Create your <a href="https://plantuml.com">PlantUML</a> diagrams directly in your browser!</p>
</div>
<div id="content">
<%-- CONTENT --%>
<form method="post" accept-charset="utf-8" action="form">
<p> <label for="text">UML Editor Content</label>
<textarea id="text" name="text" cols="120" rows="10"><%= net.sourceforge.plantuml.servlet.PlantUmlServlet.stringToHTMLString(decoded) %></textarea>
<input type="submit" value="Submit" title="Submit Code and generate diagram"/>&nbsp;
<input type="submit" value="Copy Content to Clipboard" title="Copy Content to the clipboard" onclick="copyToClipboard('text','Content');return false; ">
</p>
</form>
<hr/>
<p>You can enter here a previously generated URL:</p>
<form method="post" action="form">
<p> <label for="url">previously generated URL</label>
<input id="url" name="url" type="text" size="150" value="<%= imgurl %>" />
<br/>
<input type="submit" value="Decode URL" title="Decode URL and show code and diagram"/>&nbsp;
<input type="submit" value="Copy URL to Clipboard" title="Copy URL to the clipboard" onclick="copyToClipboard('url','URL');return false; ">
</p>
</form>
<% if (hasImg) { %>
<hr/>
<a href="<%= imgurl %>" title="View diagram as PNG">View as PNG</a>&nbsp;
<a href="<%= svgurl %>" title="View diagram as SVG">View as SVG</a>&nbsp;
<a href="<%= txturl %>" title="View diagram as ASCII Art">View as ASCII Art</a>&nbsp;
<a href="<%= pdfurl %>" title="View diagram as PDF">View as PDF</a>&nbsp;
<% if (hasMap) { %>
<a href="<%= mapurl %>">View Map Data</a>
<% } %>
<% if (showSocialButtons) { %>
<%@ include file="resource/socialbuttons2.jspf" %>
<% } %>
<p id="diagram">
<% if (!hasMap) { %>
<img src="<%= imgurl %>" alt="PlantUML diagram" />
<% } else { %>
<img src="<%= imgurl %>" alt="PlantUML diagram" usemap="#plantuml_map" />
<%= map %>
<% } %>
</p>
<% } %>
<div class="main flex-main flex-columns">
<div id="editor-main-container" class="editor flex-main flex-rows">
<div>
<div class="btn-input">
<input id="url" type="text" name="url" value="png/<%= diagramUrl %>" />
<input type="image" alt="copy" src="assets/copy.svg" onclick="copyUrlToClipboard()" />
</div>
</div>
<div class="flex-main monaco-editor-container">
<textarea id="initCode" name="initCode" style="display: none;"><%= net.sourceforge.plantuml.servlet.PlantUmlServlet.stringToHTMLString(decoded) %></textarea>
<div id="monaco-editor"></div>
<input type="image" alt="copy" src="assets/copy.svg" onclick="copyCodeToClipboard()" />
</div>
</div>
<div id="previewer-main-container" class="previewer flex-main">
<%@ include file="resource/preview.jsp" %>
</div>
</div>
<%-- FOOTER --%>
<%@ include file="footer.jspf" %>
<div class="footer">
<%@ include file="resource/footer.jsp" %>
</div>
</div>
</body>
</html>
</html>

View File

@ -2,67 +2,394 @@
* PlantUMLServlet style sheet *
******************************/
/* Font */
h1, p, #content a {
font-family: arial,helvetica,sans-serif;
/* font-size: medium; */
/************* variables *************/
:root {
color-scheme: light dark;
--border-color: #ccc;
--bg-color: inherit;
--font-color: inherit;
--settings-bg-color: #fefefe;
}
[data-theme="dark"] {
--border-color: #848484;
--bg-color: #212121;
--settings-bg-color: #424242;
--font-color: #ccc;
}
/* Header */
#header {
margin-left: auto;
margin-right: auto;
text-align: center;
/************* default settings *************/
html, body {
margin: 0;
padding: 0;
}
html {
font-family: arial,helvetica,sans-serif;
}
body {
background-color: var(--bg-color);
color: var(--font-color);
overflow: auto;
}
@media screen and (min-width: 900px) {
body {
height: 100vh;
overflow: hidden;
}
.app {
height: 100%;
}
}
/* Content */
#content {
margin-left: auto;
margin-right: auto;
width: 95%;
/************* ruler *************/
.hr {
padding: 1rem 0;
width: 100%;
}
.flex-columns > .hr {
padding: 0 1rem;
width: initial;
height: 100%;
}
.hr:after {
content: "";
display: block;
background-color: var(--border-color);
height: 100%;
width: 100%;
min-height: 3px;
min-width: 3px;
}
/* Form inputs */
#content textarea, #content .CodeMirror, #content input[type=text] {
background-color: #ffffff;
font-family: monospace;
font-size: medium;
width: 100%;
resize: vertical;
border: 3px solid #ccc !important;
/************* flex rows and columns *************/
.flex-columns {
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
.flex-rows {
display: flex;
flex-direction: column;
}
.flex-main {
flex: 1 1 1px;
overflow: auto;
}
.flex-columns > *, .flex-rows > * {
flex-shrink: 0;
}
#content input[type=text] {
border: 0;
/*******************************************************************/
/************* header, main, footer *************/
.header {
margin-left: auto;
margin-right: auto;
text-align: center;
}
.main {
margin: 1% 5%;
z-index: 1;
}
.main > div {
margin: 0 1.75%;
}
.main > div:first-child {
margin-left: 0;
}
.main > div:last-child {
margin-right: 0;
}
@media screen and (max-width: 900px) {
.main {
display: block;
overflow: inherit;
}
.main > div {
margin: 1.75% 0;
}
.main > div:first-child {
margin-top: 0;
}
.main > div:last-child {
margin-bottom: 0;
}
}
.footer p {
background-color: #eee;
color: #666;
font-size: 0.7em;
margin: 0;
padding: 0.5em;
text-align: center;
}
#content input[type="submit"] {
margin-top: 10px;
padding: 5px;
background: #fafafa;
border: 1px solid black;
/*******************************************************************/
/************* editor *************/
.editor {
border: 3px solid var(--border-color);
box-sizing: border-box;
overflow: hidden;
}
@media screen and (max-width: 900px) {
.editor {
height: 20em;
}
}
.monaco-editor-container {
overflow: hidden;
position: relative;
}
#monaco-editor {
height: 100%;
}
/* Hack to display the icons in the icon auto completion documentation in a visible size.
* (see PlantUmlLanguageFeatures.registerIconCompletion) */
#monaco-editor .overlayWidgets .suggest-details p img[alt="icon"] {
height: 1.2rem;
}
#content input[type="submit"]:hover {
background: #f0f0f0;
/************* URL input + copy button *************/
.btn-input {
align-items: center;
border-bottom: 3px solid var(--border-color);
box-sizing: border-box;
display: flex;
justify-content: center;
}
.btn-input input[type=text] {
border: 0;
flex: 1 1 1px;
font-family: monospace;
font-size: medium;
padding: 0.2em;
text-overflow: ellipsis;
}
.btn-input input[type=text]:focus {
border: 0;
box-shadow: none;
outline: none;
}
.btn-input input[type=image] {
height: 1rem;
margin-left: 0.7em;
padding: 0 0.3em;
}
/* Diagram */
#content #diagram {
text-align: center;
/************* Monaco editor copy button *************/
.monaco-editor-container input[type=image] {
height: 1.5rem;
position: absolute;
right: 2rem;
top: 1rem;
opacity: 0.5;
}
.monaco-editor-container input[type=image]:hover {
opacity: 1;
}
#content #diagram img {
border: medium solid green;
padding: 10px;
/*******************************************************************/
/************* previewer *************/
.content.viewer-content {
margin: 5%;
}
.content.viewer-content, .previewer-container {
height: 100%;
}
@media screen and (max-width: 900px) {
.previewer-container {
height: initial;
}
.previewer-main {
flex: none;
}
}
/* Footer */
#footer p {
background-color: #eee;
color: #666;
font-size: 0.7em;
padding: 2px;
text-align: center;
width: 100%;
}
/************* menu *************/
.preview-menu {
margin-left: 5%;
margin-right: 5%;
}
.diagram-link img, .btn-dock {
width: 2.5rem;
}
.btn-settings {
width: 2.2rem;
margin-left: auto;
margin-right: 0.25rem;