From 3cb10487fdc137f05d092861a0df93a3acc7aaae Mon Sep 17 00:00:00 2001
From: Alexander Girgis <11259344+AlexanderGirgis@users.noreply.github.com>
Date: Sun, 29 Mar 2020 23:30:37 +0200
Subject: [PATCH] Allow basic markup syntax custom previews
Add MarkdownFormatter using https://github.com/vsch/flexmark-java/ to format markdown.
To configure Markdown in custom previews add the "Markdown" formatter.
Markdown is enabled by default for the comment field as requested in https://github.com/JabRef/jabref/issues/6194
---
CHANGELOG.md | 1 +
build.gradle | 1 +
external-libraries.txt | 5 ++
src/main/java/module-info.java | 7 +++
.../org/jabref/logic/layout/LayoutEntry.java | 3 +
.../layout/format/MarkdownFormatter.java | 42 +++++++++++++
.../migrations/PreferencesMigrations.java | 7 +++
.../jabref/preferences/JabRefPreferences.java | 2 +-
.../layout/format/MarkdownFormatterTest.java | 60 +++++++++++++++++++
.../migrations/PreferencesMigrationsTest.java | 54 ++++++++++++++++-
10 files changed, 179 insertions(+), 3 deletions(-)
create mode 100644 src/main/java/org/jabref/logic/layout/format/MarkdownFormatter.java
create mode 100644 src/test/java/org/jabref/logic/layout/format/MarkdownFormatterTest.java
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 149ea8d8bc7..3fa07b2d99c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,7 @@ Note that this project **does not** adhere to [Semantic Versioning](http://semve
- We added support for searching ShortScience for an entry through the user's browser. [#6018](https://github.com/JabRef/jabref/pull/6018)
- We added tooltips for most fields in the entry editor containing a short description. [#5847](https://github.com/JabRef/jabref/issues/5847)
+- We added support for basic markdown in custom formatted previews [#6194](https://github.com/JabRef/jabref/issues/6194)
### Changed
diff --git a/build.gradle b/build.gradle
index b0953b82aae..48afce41006 100644
--- a/build.gradle
+++ b/build.gradle
@@ -195,6 +195,7 @@ dependencies {
exclude module: "log4j-core"
}
+ implementation 'com.vladsch.flexmark:flexmark-all:0.60.2'
testImplementation 'io.github.classgraph:classgraph:4.8.65'
testImplementation 'org.junit.jupiter:junit-jupiter:5.6.1'
diff --git a/external-libraries.txt b/external-libraries.txt
index f67e09af7fd..05e11258f7d 100644
--- a/external-libraries.txt
+++ b/external-libraries.txt
@@ -334,6 +334,11 @@ Project: OpenOffice.org
URL: http://www.openoffice.org/api/SDK
License: Apache-2.0
+Id: com.vladsch.flexmark:flexmark-all
+Project: flexmark-java
+URL: https://github.com/vsch/flexmark-java
+License: BSD-2-Clause
+
## Sorted list of runtime dependencies output by gradle
```text
diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java
index 91b721e8a4a..d04c03e13f2 100644
--- a/src/main/java/module-info.java
+++ b/src/main/java/module-info.java
@@ -82,4 +82,11 @@
requires org.antlr.antlr4.runtime;
requires flowless;
requires org.apache.tika.core;
+
+ requires flexmark;
+ requires flexmark.ext.gfm.strikethrough;
+ requires flexmark.ext.gfm.tasklist;
+ requires flexmark.util.ast;
+ requires flexmark.util.data;
+ requires annotations;
}
diff --git a/src/main/java/org/jabref/logic/layout/LayoutEntry.java b/src/main/java/org/jabref/logic/layout/LayoutEntry.java
index ec7d6067a7e..ee6632a7046 100644
--- a/src/main/java/org/jabref/logic/layout/LayoutEntry.java
+++ b/src/main/java/org/jabref/logic/layout/LayoutEntry.java
@@ -57,6 +57,7 @@
import org.jabref.logic.layout.format.JournalAbbreviator;
import org.jabref.logic.layout.format.LastPage;
import org.jabref.logic.layout.format.LatexToUnicodeFormatter;
+import org.jabref.logic.layout.format.MarkdownFormatter;
import org.jabref.logic.layout.format.NameFormatter;
import org.jabref.logic.layout.format.NoSpaceBetweenAbbreviations;
import org.jabref.logic.layout.format.NotFoundFormatter;
@@ -536,6 +537,8 @@ private LayoutFormatter getLayoutFormatterByName(String name) {
return new WrapContent();
case "WrapFileLinks":
return new WrapFileLinks(prefs.getFileLinkPreferences());
+ case "Markdown":
+ return new MarkdownFormatter();
default:
return null;
}
diff --git a/src/main/java/org/jabref/logic/layout/format/MarkdownFormatter.java b/src/main/java/org/jabref/logic/layout/format/MarkdownFormatter.java
new file mode 100644
index 00000000000..4aeff2a55ad
--- /dev/null
+++ b/src/main/java/org/jabref/logic/layout/format/MarkdownFormatter.java
@@ -0,0 +1,42 @@
+package org.jabref.logic.layout.format;
+
+import java.util.List;
+import java.util.Objects;
+
+import org.jabref.logic.layout.LayoutFormatter;
+
+import com.vladsch.flexmark.ext.gfm.strikethrough.StrikethroughExtension;
+import com.vladsch.flexmark.ext.gfm.tasklist.TaskListExtension;
+import com.vladsch.flexmark.html.HtmlRenderer;
+import com.vladsch.flexmark.parser.Parser;
+import com.vladsch.flexmark.util.ast.Node;
+import com.vladsch.flexmark.util.data.MutableDataSet;
+
+public class MarkdownFormatter implements LayoutFormatter {
+
+ private final Parser parser;
+ private final HtmlRenderer renderer;
+
+ public MarkdownFormatter() {
+ MutableDataSet options = new MutableDataSet();
+ options.set(Parser.EXTENSIONS, List.of(
+ StrikethroughExtension.create(),
+ TaskListExtension.create()
+ ));
+ options.set(HtmlRenderer.NO_P_TAGS_USE_BR, true);
+
+ parser = Parser.builder(options).build();
+ renderer = HtmlRenderer.builder(options).build();
+ }
+
+ @Override
+ public String format(final String fieldText) {
+ Objects.requireNonNull(fieldText, "Field Text should not be null, when handed to formatter");
+
+ Node document = parser.parse(fieldText);
+ String html = renderer.render(document);
+
+ // workaround HTMLChars transforming "\n" into
by returning a one liner
+ return html.replaceAll("\\r\\n|\\r|\\n", " ").trim();
+ }
+}
diff --git a/src/main/java/org/jabref/migrations/PreferencesMigrations.java b/src/main/java/org/jabref/migrations/PreferencesMigrations.java
index d841a6c0c08..d1fcd36b57a 100644
--- a/src/main/java/org/jabref/migrations/PreferencesMigrations.java
+++ b/src/main/java/org/jabref/migrations/PreferencesMigrations.java
@@ -49,6 +49,7 @@ public static void runMigrations() {
addCrossRefRelatedFieldsForAutoComplete(Globals.prefs);
upgradePreviewStyleFromReviewToComment(Globals.prefs);
upgradeColumnPreferences(Globals.prefs);
+ upgradePreviewStyleAllowMarkdown(Globals.prefs);
}
/**
@@ -301,6 +302,12 @@ static void upgradePreviewStyleFromReviewToComment(JabRefPreferences prefs) {
prefs.setPreviewStyle(migratedStyle);
}
+ static void upgradePreviewStyleAllowMarkdown(JabRefPreferences prefs) {
+ String currentPreviewStyle = prefs.getPreviewStyle();
+ String migratedStyle = currentPreviewStyle.replace("\\begin{comment}
Comment: \\format[HTMLChars]{\\comment} \\end{comment}", "\\begin{comment}
Comment: \\format[Markdown,HTMLChars]{\\comment} \\end{comment}");
+ prefs.setPreviewStyle(migratedStyle);
+ }
+
/**
* The former preferences default of columns was a simple list of strings ("author;title;year;..."). Since 5.0
* the preferences store the type of the column too, so that the formerly hardwired columns like the graphic groups
diff --git a/src/main/java/org/jabref/preferences/JabRefPreferences.java b/src/main/java/org/jabref/preferences/JabRefPreferences.java
index 096396915f3..5dddcd3b233 100644
--- a/src/main/java/org/jabref/preferences/JabRefPreferences.java
+++ b/src/main/java/org/jabref/preferences/JabRefPreferences.java
@@ -674,7 +674,7 @@ private JabRefPreferences() {
+ "\\begin{year}\\year\\end{year}\\begin{volume}, \\volume\\end{volume}"
+ "\\begin{pages}, \\format[FormatPagesForHTML]{\\pages} \\end{pages}__NEWLINE__"
+ "\\begin{abstract}
Abstract: \\format[HTMLChars]{\\abstract} \\end{abstract}__NEWLINE__"
- + "\\begin{comment}
Comment: \\format[HTMLChars]{\\comment} \\end{comment}"
+ + "\\begin{comment}
Comment: \\format[Markdown,HTMLChars]{\\comment} \\end{comment}"
+ "__NEWLINE__
Hello World
"); + } + + @Test + void formatWhenFormattingComplexMarkupThenReturnsOnlyOneLine() { + String source = "Markup\n\n* list item one\n* list item 2\n\n rest"; + assertThat(markdownFormatter.format(source)) + .contains("Markup