Skip to content

Commit

Permalink
Add mscgen support (yuzutech#12)
Browse files Browse the repository at this point in the history
Install msc-generator [1] into the server docker image and provide a
corresponding under "/mscgen".

[1] https://gitlab.com/msc-generator/msc-generator
  • Loading branch information
tmpgnh committed Sep 13, 2024
1 parent d96fd25 commit dea3577
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 0 deletions.
2 changes: 2 additions & 0 deletions server/ops/docker/jdk17-noble/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,8 @@ RUN wget "https://github.com/yuzutech/blockdiag/releases/download/v${BLOCKDIAG_V
RUN wget "https://github.com/yuzutech/WireViz/releases/download/v${WIREVIZ_VERSION}/wireviz-linux-${TARGETARCH}.bin" -O /usr/bin/wireviz && \
chmod +x /usr/bin/wireviz

RUN apt-get install --no-install-recommends --yes msc-generator-nox

COPY --from=erd /root/.cabal/bin/erd /usr/bin/erd
COPY --from=kroki-builder-bytefield /app/app.bin /usr/bin/bytefield
COPY --from=kroki-builder-dbml /app/app.bin /usr/bin/dbml
Expand Down
1 change: 1 addition & 0 deletions server/src/main/java/io/kroki/server/Server.java
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ static void start(Vertx vertx, VertxOptions vertxOptions, JsonObject config, Han
registry.register(new TikZ(vertx, config, commander), "tikz");
registry.register(new Dbml(vertx, config, commander), "dbml");
registry.register(new Wireviz(vertx, config, commander), "wireviz");
registry.register(new MscGenerator(vertx, config, commander), "mscgen");

router.post("/")
.handler(bodyHandler)
Expand Down
85 changes: 85 additions & 0 deletions server/src/main/java/io/kroki/server/service/MscGenerator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package io.kroki.server.service;

import io.kroki.server.action.Commander;
import io.kroki.server.decode.DiagramSource;
import io.kroki.server.decode.SourceDecoder;
import io.kroki.server.error.DecodeException;
import io.kroki.server.format.FileFormat;
import io.vertx.core.AsyncResult;
import io.vertx.core.Handler;
import io.vertx.core.Vertx;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.json.JsonObject;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class MscGenerator implements DiagramService {

private static final List<FileFormat> SUPPORTED_FORMATS = Arrays.asList(FileFormat.PNG, FileFormat.SVG, FileFormat.PDF);

private final Vertx vertx;
private final String binPath;
private final SourceDecoder sourceDecoder;
private final Commander commander;

public MscGenerator(Vertx vertx, JsonObject config, Commander commander) {
this.vertx = vertx;
this.binPath = config.getString("KROKI_MSCGEN_BIN_PATH", "msc-gen");
this.sourceDecoder = new SourceDecoder() {
@Override
public String decode(String encoded) throws DecodeException {
return DiagramSource.decode(encoded);
}
};
this.commander = commander;
}

@Override
public List<FileFormat> getSupportedFormats() {
return SUPPORTED_FORMATS;
}

@Override
public SourceDecoder getSourceDecoder() {
return sourceDecoder;
}

@Override
public String getVersion() {
try {
Process process = new ProcessBuilder(binPath, "--version").start();
String line = new BufferedReader(new InputStreamReader(process.getInputStream())).readLine();
return line.split("\\s+")[1].substring(1);
} catch (IOException e) {
return "unknown";
}
}

@Override
public void convert(String sourceDecoded, String serviceName, FileFormat fileFormat, JsonObject options, Handler<AsyncResult<Buffer>> handler) {
vertx.executeBlocking(future -> {
try {
byte[] result = mscgen(sourceDecoded.getBytes(), fileFormat.getName(), options);
future.complete(result);
} catch (IOException | InterruptedException | IllegalStateException e) {
future.fail(e);
}
}, res -> handler.handle(res.map(o -> Buffer.buffer((byte[]) o))));
}

private byte[] mscgen(byte[] source, String format, JsonObject options) throws IOException, InterruptedException, IllegalStateException {
return commander.execute(
source,
binPath,
"-S", options.getString("lang", "signalling"), // Supported languages: signalling | msc, graph, block
"-T", format,
"-s=" + options.getFloat("scale", 1.f),
"-"
);
}
}

0 comments on commit dea3577

Please sign in to comment.