Picto: add Kroki integration
diff --git a/plugins/org.eclipse.epsilon.picto/plugin.xml b/plugins/org.eclipse.epsilon.picto/plugin.xml
index 07ad0e4..66ca23f 100644
--- a/plugins/org.eclipse.epsilon.picto/plugin.xml
+++ b/plugins/org.eclipse.epsilon.picto/plugin.xml
@@ -108,6 +108,9 @@
<viewContentTransformer
class="org.eclipse.epsilon.picto.transformers.CsvContentTransformer">
</viewContentTransformer>
+ <viewContentTransformer
+ class="org.eclipse.epsilon.picto.transformers.KrokiContentTransformer">
+ </viewContentTransformer>
</extension>
<extension
point="org.eclipse.epsilon.picto.browserFunction">
diff --git a/plugins/org.eclipse.epsilon.picto/src/org/eclipse/epsilon/picto/preferences/PictoPreferencePage.java b/plugins/org.eclipse.epsilon.picto/src/org/eclipse/epsilon/picto/preferences/PictoPreferencePage.java
index b4e9dbc..a6dad39 100644
--- a/plugins/org.eclipse.epsilon.picto/src/org/eclipse/epsilon/picto/preferences/PictoPreferencePage.java
+++ b/plugins/org.eclipse.epsilon.picto/src/org/eclipse/epsilon/picto/preferences/PictoPreferencePage.java
@@ -17,36 +17,59 @@
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.preference.IntegerFieldEditor;
import org.eclipse.jface.preference.PreferencePage;
+import org.eclipse.jface.preference.StringFieldEditor;
import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPreferencePage;
public class PictoPreferencePage extends PreferencePage implements IWorkbenchPreferencePage {
public static final String ID = "org.eclipse.epsilon.picto.preferences.PictoPreferencePage";
+
public static final String PROPERTY_RENDER_VERBATIM = "verbatim.sources";
+ public static final boolean DEFAULT_RENDER_VERBATIM = false;
+
public static final String TIMEOUT = "external.timeout";
public static final int DEFAULT_TIMEOUT = 60;
+
+ public static final String KROKI_URL = "kroki.url";
+ public static final String DEFAULT_KROKI_URL = "https://kroki.io";
protected final ArrayList<FieldEditor> fieldEditors = new ArrayList<>();
- protected IPreferenceStore preferences = EpsilonCommonsPlugin.getDefault().getPreferenceStore();
+ protected final IPreferenceStore preferences = EpsilonCommonsPlugin.getDefault().getPreferenceStore();
+
+ private IntegerFieldEditor timeoutEditor;
+ private BooleanFieldEditor verbatimBooleanEditor;
+ private StringFieldEditor krokiURLEditor;
public PictoPreferencePage() {
+ preferences.setDefault(PROPERTY_RENDER_VERBATIM, DEFAULT_RENDER_VERBATIM);
preferences.setDefault(TIMEOUT, DEFAULT_TIMEOUT);
+ preferences.setDefault(KROKI_URL, DEFAULT_KROKI_URL);
}
-
+
@Override
protected Control createContents(Composite parent) {
final Composite composite = new Composite(parent, SWT.FILL);
- final IntegerFieldEditor timeoutEditor = new IntegerFieldEditor(TIMEOUT, "Rendering timeout (seconds)", composite);
- final BooleanFieldEditor verbatimBooleanEditor = new BooleanFieldEditor(PROPERTY_RENDER_VERBATIM, "Render verbatim sources", composite);
-
+ timeoutEditor = new IntegerFieldEditor(TIMEOUT, "Rendering timeout (seconds)", composite);
+
+ verbatimBooleanEditor = new BooleanFieldEditor(PROPERTY_RENDER_VERBATIM, "Render verbatim sources", composite);
+ // Fills in the second column in the field editor
+ new Label(parent, SWT.NONE);
+
+ final Label lblSeparator = new Label(composite, SWT.SEPARATOR | SWT.HORIZONTAL);
+ lblSeparator.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false, 2, 1));
+ krokiURLEditor = new StringFieldEditor(KROKI_URL, "Kroki server base URL", composite);
+
fieldEditors.add(verbatimBooleanEditor);
fieldEditors.add(timeoutEditor);
-
+ fieldEditors.add(krokiURLEditor);
+
for (FieldEditor fieldEditor : fieldEditors) {
fieldEditor.setPreferenceStore(preferences);
fieldEditor.load();
@@ -70,4 +93,13 @@
return true;
}
+ @Override
+ protected void performDefaults() {
+ timeoutEditor.loadDefault();
+ verbatimBooleanEditor.loadDefault();
+ krokiURLEditor.loadDefault();
+
+ super.performDefaults();
+ }
+
}
diff --git a/plugins/org.eclipse.epsilon.picto/src/org/eclipse/epsilon/picto/transformers/KrokiContentTransformer.java b/plugins/org.eclipse.epsilon.picto/src/org/eclipse/epsilon/picto/transformers/KrokiContentTransformer.java
new file mode 100644
index 0000000..67f748e
--- /dev/null
+++ b/plugins/org.eclipse.epsilon.picto/src/org/eclipse/epsilon/picto/transformers/KrokiContentTransformer.java
@@ -0,0 +1,82 @@
+/*********************************************************************
+* Copyright (c) 2022 The University of York.
+*
+* This program and the accompanying materials are made
+* available under the terms of the Eclipse Public License 2.0
+* which is available at https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+**********************************************************************/
+package org.eclipse.epsilon.picto.transformers;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+import org.eclipse.epsilon.common.dt.EpsilonCommonsPlugin;
+import org.eclipse.epsilon.picto.PictoView;
+import org.eclipse.epsilon.picto.ViewContent;
+import org.eclipse.epsilon.picto.preferences.PictoPreferencePage;
+import org.eclipse.jface.preference.IPreferenceStore;
+
+public class KrokiContentTransformer implements ViewContentTransformer {
+
+ private static final Pattern KROKI_FORMAT_REGEX = Pattern.compile("kroki-(?<format>[a-zA-Z]+)", Pattern.CASE_INSENSITIVE);
+
+ @Override
+ public boolean canTransform(ViewContent content) {
+ return KROKI_FORMAT_REGEX.matcher(content.getFormat()).matches();
+ }
+
+ @Override
+ public String getLabel(ViewContent content) {
+ return "Kroki";
+ }
+
+ @Override
+ public ViewContent transform(ViewContent content, PictoView pictoView) throws Exception {
+ final Matcher matcher = KROKI_FORMAT_REGEX.matcher(content.getFormat());
+
+ if (matcher.matches()) {
+ final String format = matcher.group("format");
+ return new ViewContent("svg", krokiToRawSvg(format, content.getText()), content);
+ } else {
+ return new ViewContent("text", String.format("BUG: Kroki format could not be extracted from '%s'", content.getFormat()), content);
+ }
+ }
+
+ private String krokiToRawSvg(String format, String text) throws IOException {
+ final URL url = new URL(String.format("%s/%s/svg", getKrokiBaseURL(), format));
+
+ final HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+ conn.setDoOutput(true);
+ conn.setRequestMethod("POST");
+ conn.setRequestProperty("Content-Type", "text-plain");
+ try (OutputStream os = conn.getOutputStream(); OutputStreamWriter osw = new OutputStreamWriter(os, "UTF-8")) {
+ osw.write(text);
+ }
+ conn.connect();
+
+ String svgOutput = new BufferedReader(
+ new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8))
+ .lines()
+ .collect(Collectors.joining("\n"));
+
+ return svgOutput;
+ }
+
+ private String getKrokiBaseURL() {
+ IPreferenceStore preferenceStore = EpsilonCommonsPlugin.getDefault().getPreferenceStore();
+ return preferenceStore.isDefault(PictoPreferencePage.KROKI_URL)
+ ? PictoPreferencePage.DEFAULT_KROKI_URL : preferenceStore.getString(PictoPreferencePage.KROKI_URL);
+ }
+
+}