implemented adding targets to links in markdown

Signed-off-by: Stephan Richter <s.richter@srsoftware.de>
This commit is contained in:
2026-05-19 09:53:43 +02:00
parent 9bec33d5de
commit aa48bbcbf5
2 changed files with 33 additions and 2 deletions
@@ -80,7 +80,7 @@ public class Application {
new DocumentApi(config).bindPath("/api/document").on(server); new DocumentApi(config).bindPath("/api/document").on(server);
new UserLegacy(config).bindPath("/legacy/user").on(server); new UserLegacy(config).bindPath("/legacy/user").on(server);
new NotesLegacy(config).bindPath("/legacy/notes").on(server); new NotesLegacy(config).bindPath("/legacy/notes").on(server);
new MarkdownApi().bindPath("/api/markdown").on(server); new MarkdownApi(config).bindPath("/api/markdown").on(server);
new NoteModule(config).bindPath("/api/notes").on(server); new NoteModule(config).bindPath("/api/notes").on(server);
new StockModule(config).bindPath("/api/stock").on(server); new StockModule(config).bindPath("/api/stock").on(server);
new PollModule(config).bindPath("/api/poll").on(server); new PollModule(config).bindPath("/api/poll").on(server);
@@ -3,21 +3,34 @@ package de.srsoftware.umbrella.markdown;
import static de.srsoftware.tools.MimeType.MIME_HTML; import static de.srsoftware.tools.MimeType.MIME_HTML;
import static de.srsoftware.umbrella.core.ModuleRegistry.userService; import static de.srsoftware.umbrella.core.ModuleRegistry.userService;
import static de.srsoftware.umbrella.core.constants.Field.BASE_URL;
import static de.srsoftware.umbrella.core.exceptions.UmbrellaException.missingField;
import com.sun.net.httpserver.HttpExchange; import com.sun.net.httpserver.HttpExchange;
import de.srsoftware.configuration.Configuration;
import de.srsoftware.tools.Path; import de.srsoftware.tools.Path;
import de.srsoftware.umbrella.core.BaseHandler; import de.srsoftware.umbrella.core.BaseHandler;
import de.srsoftware.umbrella.core.ModuleRegistry; import de.srsoftware.umbrella.core.ModuleRegistry;
import de.srsoftware.umbrella.core.Util; import de.srsoftware.umbrella.core.Util;
import de.srsoftware.umbrella.core.api.MarkdownService; import de.srsoftware.umbrella.core.api.MarkdownService;
import de.srsoftware.umbrella.core.constants.Field;
import de.srsoftware.umbrella.core.exceptions.UmbrellaException; import de.srsoftware.umbrella.core.exceptions.UmbrellaException;
import java.io.IOException; import java.io.IOException;
import java.util.Optional;
import java.util.regex.Pattern;
public class MarkdownApi extends BaseHandler implements MarkdownService { public class MarkdownApi extends BaseHandler implements MarkdownService {
private static Pattern ANCHOR = Pattern.compile("(?is)<a\\b[^>]*>.*?</a>");
private static Pattern HREF = Pattern.compile("(?i)\\bhref\\s*=\\s*(?:\"([^\"]*)\"|'([^']*)'|([^\\s>]+))");
private static Pattern TARGET = Pattern.compile("(?i)\\btarget\\s*=");
private final String baseUrl;
public MarkdownApi() { public MarkdownApi(Configuration config) {
super(); super();
Optional<String> baseUrl = config.get(BASE_URL);
if (baseUrl.isEmpty()) throw missingField(BASE_URL);
this.baseUrl = baseUrl.get();
ModuleRegistry.add(this); ModuleRegistry.add(this);
} }
@@ -29,6 +42,24 @@ public class MarkdownApi extends BaseHandler implements MarkdownService {
if (user.isEmpty()) throw UmbrellaException.forbidden("You must be logged in to use the markdown renderer!"); if (user.isEmpty()) throw UmbrellaException.forbidden("You must be logged in to use the markdown renderer!");
var rendered = Util.markdown(body(ex)); var rendered = Util.markdown(body(ex));
var anchors = ANCHOR.matcher(rendered);
while (anchors.find()){
String anchor = anchors.group();
var urls = HREF.matcher(anchor);
if (!urls.find()) continue; // no url → nothing to do
var href = urls.group(1) != null ? urls.group(1) : (urls.group(2) != null ? urls.group(2) : urls.group(3));
var target = TARGET.matcher(anchor);
if (target.find()) continue; // target already set → leave untouched
if (!href.startsWith("http")) continue; // relative url? good!
if (!href.startsWith(baseUrl)) { // add target
var replacement = "<a target=\"_blank\""+anchor.substring(2);
rendered = rendered.replace(anchor, replacement);
anchors.reset(rendered);
}
}
ex.getResponseHeaders().add(CONTENT_TYPE,MIME_HTML); ex.getResponseHeaders().add(CONTENT_TYPE,MIME_HTML);
return sendContent(ex,rendered); return sendContent(ex,rendered);
} catch (UmbrellaException e){ } catch (UmbrellaException e){