Skip to content

Commit

Permalink
Markdown Export Formatter (#12220)
Browse files Browse the repository at this point in the history
* Add Markdown export formatter

* updated the changelog

* fix checkstyle and l10n

* fix import order

* Update CHANGELOG.md

Co-authored-by: Carl Christian Snethlage <[email protected]>

* Add full stop (changelog)

* remove explicit save order - just for test

* checkstyle

* temp dir

---------

Co-authored-by: Carl Christian Snethlage <[email protected]>
Co-authored-by: Subhramit Basu Bhowmick <[email protected]>
Co-authored-by: Siedlerchr <[email protected]>
  • Loading branch information
4 people authored Nov 25, 2024
1 parent dc9c49f commit b453985
Show file tree
Hide file tree
Showing 9 changed files with 201 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv

### Added

- We added a Markdown export layout. [#12220](https://github.com/JabRef/jabref/pull/12220)
- We added a "view as BibTeX" option before importing an entry from the citation relation tab. [#11826](https://github.com/JabRef/jabref/issues/11826)
- We added support finding LaTeX-encoded special characters based on plain Unicode and vice versa. [#11542](https://github.com/JabRef/jabref/pull/11542)
- When a search hits a file, the file icon of that entry is changed accordingly. [#11542](https://github.com/JabRef/jabref/pull/11542)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ public static ExporterFactory create(CliPreferences preferences) {
exporters.add(new TemplateExporter(Localization.lang("HTML table"), "tablerefs", "tablerefs", "tablerefs", StandardFileType.HTML, layoutPreferences, saveOrder));
exporters.add(new TemplateExporter(Localization.lang("HTML list"), "listrefs", "listrefs", "listrefs", StandardFileType.HTML, layoutPreferences, saveOrder));
exporters.add(new TemplateExporter(Localization.lang("HTML table (with Abstract & BibTeX)"), "tablerefsabsbib", "tablerefsabsbib", "tablerefsabsbib", StandardFileType.HTML, layoutPreferences, saveOrder));
exporters.add(new TemplateExporter(Localization.lang("Markdown titles"), "title-md", "title-md", "title-markdown", StandardFileType.MARKDOWN, layoutPreferences, saveOrder));
exporters.add(new TemplateExporter("Harvard RTF", "harvard", "harvard", "harvard", StandardFileType.RTF, layoutPreferences, saveOrder));
exporters.add(new TemplateExporter("ISO 690 RTF", "iso690rtf", "iso690RTF", "iso690rtf", StandardFileType.RTF, layoutPreferences, saveOrder));
exporters.add(new TemplateExporter("ISO 690", "iso690txt", "iso690", "iso690txt", StandardFileType.TXT, layoutPreferences, saveOrder));
Expand Down
2 changes: 2 additions & 0 deletions src/main/resources/l10n/JabRef_en.properties
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,8 @@ The\ marked\ area\ does\ not\ contain\ any\ legible\ text!=The marked area does

HTML\ table=HTML table
HTML\ table\ (with\ Abstract\ &\ BibTeX)=HTML table (with Abstract & BibTeX)
Markdown\ titles=Markdown titles

Icon=Icon

Ignore=Ignore
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* \format[RemoveLatexCommands,HTMLChars]{\title}. \begin{journal}\format[RemoveLatexCommands,HTMLChars]{\journal}\end{journal}\begin{year} \format{\year}\end{year}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* \format[RemoveLatexCommands,HTMLChars]{\title}.\begin{publisher} \format[RemoveLatexCommands,HTMLChars]{\publisher}\end{publisher} \format{\year}\end{year}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* \format[RemoveLatexCommands,HTMLChars]{\title}. \begin{booktitle}\format[RemoveLatexCommands,HTMLChars]{\booktitle}\end{booktitle}\begin{publisher}, \format[RemoveLatexCommands,HTMLChars]{\publisher}\end{publisher} \format{\year}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* \format[RemoveLatexCommands,HTMLChars]{\title}. \begin{publisher}\format[RemoveLatexCommands,HTMLChars]{\publisher} \end{publisher}\begin{series}\format[RemoveLatexCommands,HTMLChars]{\series}\end{series}\begin{!series}\format[RemoveLatexCommands,HTMLChars]{\booktitle} \format{\year}\end{!series}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* \format[RemoveLatexCommands,HTMLChars]{\title}.\begin{year} \year\end{year}
192 changes: 192 additions & 0 deletions src/test/java/org/jabref/logic/exporter/MarkdownTitleExporterTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
package org.jabref.logic.exporter;

import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collections;
import java.util.List;

import org.jabref.logic.layout.LayoutFormatterPreferences;
import org.jabref.logic.util.StandardFileType;
import org.jabref.model.database.BibDatabaseContext;
import org.jabref.model.entry.BibEntry;
import org.jabref.model.entry.field.StandardField;
import org.jabref.model.entry.types.StandardEntryType;
import org.jabref.model.metadata.SaveOrder;
import org.jabref.model.metadata.SelfContainedSaveOrder;

import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import org.mockito.Answers;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.mock;

class MarkdownTitleExporterTest {

private static Exporter htmlWebsiteExporter;
private static BibDatabaseContext databaseContext;
private static final SelfContainedSaveOrder SAVE_MOST_RECENT_FIRST_SAVE_ORDER = new SelfContainedSaveOrder(SaveOrder.OrderType.SPECIFIED, List.of(new SaveOrder.SortCriterion(StandardField.YEAR, true)));

@BeforeAll
static void setUp() {
htmlWebsiteExporter = new TemplateExporter(
"Title-Markdown",
"title-md",
"title-md",
"title-markdown",
StandardFileType.MARKDOWN,
mock(LayoutFormatterPreferences.class, Answers.RETURNS_DEEP_STUBS),
SAVE_MOST_RECENT_FIRST_SAVE_ORDER,
BlankLineBehaviour.DELETE_BLANKS);

databaseContext = new BibDatabaseContext();
}

@Test
final void exportForNoEntriesWritesNothing(@TempDir Path tempDir) throws Exception {
Path file = tempDir.resolve("ThisIsARandomlyNamedFile");
Files.createFile(file);
htmlWebsiteExporter.export(databaseContext, tempDir, Collections.emptyList());
assertEquals(Collections.emptyList(), Files.readAllLines(file));
}

@Test
final void exportsCorrectContentArticle(@TempDir Path tempDir) throws Exception {
BibEntry entry = new BibEntry(StandardEntryType.Article)
.withCitationKey("test")
.withField(StandardField.AUTHOR, "Test Author")
.withField(StandardField.TITLE, "Test Title")
.withField(StandardField.JOURNAL, "Journal of this \\& that")
.withField(StandardField.PUBLISHER, "THE PRESS")
.withField(StandardField.YEAR, "2020");

Path file = tempDir.resolve("RandomFileName");
Files.createFile(file);
htmlWebsiteExporter.export(databaseContext, file, Collections.singletonList(entry));

List<String> expected = List.of(
"* Test Title. Journal of this &amp; that 2020");

assertEquals(expected, Files.readAllLines(file));
}

@Test
final void exportsCorrectContentInCollection(@TempDir Path tempDir) throws Exception {
BibEntry entry = new BibEntry(StandardEntryType.InCollection)
.withCitationKey("test")
.withField(StandardField.AUTHOR, "Test Author")
.withField(StandardField.TITLE, "Test Title")
.withField(StandardField.BOOKTITLE, "Test book")
.withField(StandardField.PUBLISHER, "PRESS")
.withField(StandardField.YEAR, "2020");

Path file = tempDir.resolve("RandomFileName");
Files.createFile(file);
htmlWebsiteExporter.export(databaseContext, file, Collections.singletonList(entry));

List<String> expected = List.of(
"* Test Title. Test book, PRESS 2020");

assertEquals(expected, Files.readAllLines(file));
}

@Test
final void exportsCorrectContentBook(@TempDir Path tempDir) throws Exception {
BibEntry entry = new BibEntry(StandardEntryType.Book)
.withCitationKey("test")
.withField(StandardField.AUTHOR, "Test Author")
.withField(StandardField.TITLE, "Test Title")
.withField(StandardField.BOOKTITLE, "Test book")
.withField(StandardField.PUBLISHER, "PRESS")
.withField(StandardField.YEAR, "2020");

Path file = tempDir.resolve("RandomFileName");
Files.createFile(file);
htmlWebsiteExporter.export(databaseContext, file, Collections.singletonList(entry));

List<String> expected = List.of(
"* Test Title. PRESS 2020");

assertEquals(expected, Files.readAllLines(file));
}

@Test
final void exportsCorrectContentInProceeedingsPublisher(@TempDir Path tempDir) throws Exception {
BibEntry entry = new BibEntry(StandardEntryType.InProceedings)
.withCitationKey("test")
.withField(StandardField.AUTHOR, "Test Author")
.withField(StandardField.TITLE, "Test Title")
.withField(StandardField.BOOKTITLE, "Test Conference")
.withField(StandardField.PUBLISHER, "ACM")
.withField(StandardField.SERIES, "CONF'20")
.withField(StandardField.YEAR, "2020");

Path file = tempDir.resolve("RandomFileName");
Files.createFile(file);
htmlWebsiteExporter.export(databaseContext, file, Collections.singletonList(entry));

List<String> expected = List.of(
"* Test Title. ACM CONF'20");

assertEquals(expected, Files.readAllLines(file));
}

@Test
final void exportsCorrectContentInProceeedingsNoPublisher(@TempDir Path tempDir) throws Exception {
BibEntry entry = new BibEntry(StandardEntryType.InProceedings)
.withCitationKey("test")
.withField(StandardField.AUTHOR, "Test Author")
.withField(StandardField.TITLE, "Test Title")
.withField(StandardField.BOOKTITLE, "Test Conference")
.withField(StandardField.SERIES, "CONF'20")
.withField(StandardField.YEAR, "2020");

Path file = tempDir.resolve("RandomFileName");
Files.createFile(file);
htmlWebsiteExporter.export(databaseContext, file, Collections.singletonList(entry));

List<String> expected = List.of(
"* Test Title. CONF'20");

assertEquals(expected, Files.readAllLines(file));
}

@Test
final void exportsCorrectContentInProceeedingsNoSeries(@TempDir Path tempDir) throws Exception {
BibEntry entry = new BibEntry(StandardEntryType.InProceedings)
.withCitationKey("test")
.withField(StandardField.AUTHOR, "Test Author")
.withField(StandardField.TITLE, "Test Title")
.withField(StandardField.BOOKTITLE, "Test Conference")
.withField(StandardField.YEAR, "2020");

Path file = tempDir.resolve("RandomFileName");
Files.createFile(file);
htmlWebsiteExporter.export(databaseContext, file, Collections.singletonList(entry));

List<String> expected = List.of(
"* Test Title. Test Conference 2020");

assertEquals(expected, Files.readAllLines(file));
}

@Test
final void exportsCorrectContentBracketsInTitle(@TempDir Path tempDir) throws Exception {
BibEntry entry = new BibEntry(StandardEntryType.Article)
.withCitationKey("test")
.withField(StandardField.AUTHOR, "Test Author")
.withField(StandardField.TITLE, "This is {JabRef}")
.withField(StandardField.JOURNAL, "Journal of this \\& that")
.withField(StandardField.YEAR, "2020");

Path file = tempDir.resolve("RandomFileName");
Files.createFile(file);
htmlWebsiteExporter.export(databaseContext, file, Collections.singletonList(entry));

List<String> expected = List.of(
"* This is JabRef. Journal of this &amp; that 2020");

assertEquals(expected, Files.readAllLines(file));
}
}

0 comments on commit b453985

Please sign in to comment.