diff --git a/Dockerfile b/Dockerfile index 63433f22..e5006505 100644 --- a/Dockerfile +++ b/Dockerfile @@ -22,8 +22,9 @@ RUN adduser -D umbrella COPY --from=java_build /Umbrella/backend/build/libs/backend.jar /home/umbrella/jar/ RUN chown -R umbrella /home/umbrella ADD https://github.com/plantuml/plantuml/releases/download/v1.2025.10/plantuml-1.2025.10.jar /home/umbrella/plantuml.jar -USER umbrella WORKDIR /home/umbrella +RUN chmod a+rx plantuml.jar +USER umbrella RUN mkdir .config && ln -s /host/config.json .config/Umbrella.json EXPOSE 80 CMD java -jar jar/backend.jar diff --git a/core/src/main/java/de/srsoftware/umbrella/core/Util.java b/core/src/main/java/de/srsoftware/umbrella/core/Util.java index ee909fa1..a6c03005 100644 --- a/core/src/main/java/de/srsoftware/umbrella/core/Util.java +++ b/core/src/main/java/de/srsoftware/umbrella/core/Util.java @@ -35,11 +35,12 @@ import org.json.JSONObject; public class Util { public static final System.Logger LOG = System.getLogger("Util"); - private static final Pattern UML_PATTERN = Pattern.compile("@start(\\w+)(.*)@end(\\1)",Pattern.DOTALL); + private static final Pattern UML_PATTERN = Pattern.compile("@start(\\w+)(.*?)@end(\\1)",Pattern.DOTALL); private static File plantumlJar = null; private static final JParsedown MARKDOWN = new JParsedown(); public static final String SHA1 = "SHA-1"; private static final MessageDigest SHA1_DIGEST; + private static final Map umlCache = new HashMap<>(); static { try { @@ -79,11 +80,22 @@ public class Util { try { if (plantumlJar != null && plantumlJar.exists()) { var matcher = UML_PATTERN.matcher(source); - if (matcher.find()) { + while (matcher.find()) { var uml = matcher.group(0).trim(); var start = matcher.start(0); var end = matcher.end(0); + var umlHash = uml.hashCode(); + LOG.log(DEBUG,"Hash of Plantuml code: {0}",umlHash); + var svg = umlCache.get(umlHash); + if (svg != null){ + LOG.log(DEBUG,"Serving Plantuml generated SVG from cache…"); + source = source.substring(0, start) + svg + source.substring(end); + matcher = UML_PATTERN.matcher(source); + continue; + } + + LOG.log(DEBUG,"Cache miss. Generating SVG from plantuml code…"); ProcessBuilder processBuilder = new ProcessBuilder("java", "-jar", plantumlJar.getAbsolutePath(), "-tsvg", "-pipe"); var ignored = processBuilder.redirectErrorStream(); var process = processBuilder.start(); @@ -94,8 +106,11 @@ public class Util { try (InputStream is = process.getInputStream()) { byte[] out = is.readAllBytes(); - var svg = new String(out, UTF_8); + LOG.log(DEBUG,"Generated SVG. Pushing to cache…"); + svg = new String(out, UTF_8); + umlCache.put(umlHash,svg); source = source.substring(0, start) + svg + source.substring(end); + matcher = UML_PATTERN.matcher(source); } } } diff --git a/web/src/main/resources/web/css/bloodshed.css b/web/src/main/resources/web/css/bloodshed.css index 497737b0..76238700 100644 --- a/web/src/main/resources/web/css/bloodshed.css +++ b/web/src/main/resources/web/css/bloodshed.css @@ -57,8 +57,9 @@ footer { margin: 5px; } -img { +img, svg { max-width: 100%; + height: auto !important; } nav { diff --git a/web/src/main/resources/web/css/default.css b/web/src/main/resources/web/css/default.css index e0b559e1..6c8296b0 100644 --- a/web/src/main/resources/web/css/default.css +++ b/web/src/main/resources/web/css/default.css @@ -57,8 +57,9 @@ footer { margin: 5px; } -img { +img, svg { max-width: 100%; + height: auto !important; } nav { diff --git a/web/src/main/resources/web/css/winter.css b/web/src/main/resources/web/css/winter.css index 6847d7e3..3c239254 100644 --- a/web/src/main/resources/web/css/winter.css +++ b/web/src/main/resources/web/css/winter.css @@ -57,17 +57,18 @@ footer { margin: 5px; } -img { +img, svg { max-width: 100%; + height: auto !important; } nav { - position: sticky; - z-index: 100; - top: 0; - padding: 5px; - margin: 0 0 10px 0; - border-bottom: 1px solid; + position: sticky; + z-index: 100; + top: 0; + padding: 5px; + margin: 0 0 10px 0; + border-bottom: 1px solid; } td, tr{