Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
48450d4
modification des fichiers qui font la configuration des exporters
sadok-lajmi Nov 5, 2025
65bbc44
Adding the empty layouts in resources/resource/layout/academicpages
GreLucie Nov 5, 2025
a4e2fea
création du fichier academicpages.article.layout
sadok-lajmi Nov 5, 2025
3e34b92
utilisation du fichier article.layout pour le new TemplateExporter
sadok-lajmi Nov 5, 2025
8e76f57
generalisation du layout en utilisant academicpages.layout
sadok-lajmi Nov 5, 2025
2799f1d
améliorations au academicpages layout
sadok-lajmi Nov 6, 2025
be96c94
ajout d'un custom formatter to help with academic layout
sadok-lajmi Nov 25, 2025
1421e98
AcademicPagesExporter
GreLucie Nov 26, 2025
e4a987c
test: add AcademicPagesExporter tests
AloisHasNeurons Nov 28, 2025
df7aa05
Delete unecessary imports
GreLucie Nov 29, 2025
9b12666
Changelog
GreLucie Nov 29, 2025
f588da4
Changed CHANGELOG.md
GreLucie Nov 29, 2025
de65527
trying to fix the CHANGELOG.md
GreLucie Nov 29, 2025
2d8afcf
Adding blankspace in CHANGELOG.md
GreLucie Nov 29, 2025
4ea372d
Correction du nouveau exporter + Cohérence des noms des fichiers prod…
sadok-lajmi Nov 29, 2025
3972b34
Merge remote-tracking branch 'origin/fix-for-issue-12727' into fix-fo…
sadok-lajmi Nov 29, 2025
9b8a86d
Reverted the date on the CHANGELOG.md and one change on AcademicPages…
GreLucie Dec 1, 2025
9087390
revert all changes to Changelog.md
GreLucie Dec 1, 2025
655afe3
format correction for the file : LayoutEntry
sadok-lajmi Dec 2, 2025
4d7dac1
Merge remote-tracking branch 'origin/fix-for-issue-12727' into fix-fo…
sadok-lajmi Dec 2, 2025
30e7626
trying to fix Open Rewrite problem
GreLucie Dec 2, 2025
6e07a52
Refactor AcademicPagesExporterTest to use full content comparison
AloisHasNeurons Dec 2, 2025
01f43cc
Merge branch 'fix-for-issue-12727' of https://github.com/GreLucie/jab…
AloisHasNeurons Dec 2, 2025
ad339be
Removed false import statement in tests.
AloisHasNeurons Dec 2, 2025
aaa5855
deleted useless import in AcademicPagesExporter.java
GreLucie Dec 2, 2025
3547cd0
Merge branch 'fix-for-issue-12727' of https://github.com/GreLucie/jab…
GreLucie Dec 2, 2025
7b55f27
correction of the error given by the localizationconsistancy test
sadok-lajmi Dec 2, 2025
ec19bb9
Merge branch 'main' into fix-for-issue-12727
sadok-lajmi Dec 4, 2025
05792cb
Merge branch 'main' into fix-for-issue-12727
GreLucie Dec 5, 2025
7ccbc6f
Updated CHANGELOG.md
GreLucie Dec 5, 2025
6f25e5c
added the link to issue 12727
GreLucie Dec 5, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 custom exporter for academicpages and added the layout format for academic pages. [#12727](https://github.com/JabRef/jabref/issues/12727)
- We added a drop-down menu to those custom fields in the main table for which content selector values exists. [#14087](https://github.com/JabRef/jabref/issues/14087)
- We added a "Jump to Field" dialog (`Ctrl+J`) to quickly search for and navigate to any field across all tabs. [#12276](https://github.com/JabRef/jabref/issues/12276).
- We added "IEEE" as another option for parsing plain text citations. [#14233](github.com/JabRef/jabref/pull/14233)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
package org.jabref.logic.exporter;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;

import org.jabref.logic.journals.JournalAbbreviationLoader;
import org.jabref.logic.journals.JournalAbbreviationRepository;
import org.jabref.logic.layout.LayoutFormatterPreferences;
import org.jabref.logic.layout.format.HTMLChars;
import org.jabref.logic.layout.format.RemoveLatexCommandsFormatter;
import org.jabref.logic.layout.format.Replace;
import org.jabref.logic.layout.format.SafeFileName;
import org.jabref.logic.util.StandardFileType;
import org.jabref.logic.util.io.FileUtil;
import org.jabref.model.database.BibDatabaseContext;
import org.jabref.model.entry.BibEntry;
import org.jabref.model.metadata.SelfContainedSaveOrder;

import org.jspecify.annotations.NonNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* A custom exporter to write multiple bib entries as AcademicPages Markdown format.
*/
public class AcademicPagesExporter extends Exporter {
private static final String BLANK_LINE_PATTERN = "\\r\\n|\\n";
private static final String LAYOUT_PREFIX = "/resource/layout/";
private static final String LAYOUT_EXTENSION = ".layout";
private static final String FORMATTERS_EXTENSION = ".formatters";
private static final String BEGIN_INFIX = ".begin";
private static final String END_INFIX = ".end";

private static final Logger LOGGER = LoggerFactory.getLogger(AcademicPagesExporter.class);

private final String lfFileName;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not abbreviate. Use layoutFileFileName or short layoutFile (because you don't have layoutFileContent.

private final String directory;
private final LayoutFormatterPreferences layoutPreferences;
private final SelfContainedSaveOrder saveOrder;
private boolean customExport;
private List<BibEntry> entries;
private TemplateExporter academicPagesTemplate;

/**
* Initialize another export format based on templates stored in dir with layoutFile lfFilename.
*
*/
Comment on lines +47 to +50
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment is strange. What is lfFilename? Where does it come from? I think, this is not something a user of the class should know. You can just delete whole JavaDoc comment.

public AcademicPagesExporter(LayoutFormatterPreferences layoutPreferences, SelfContainedSaveOrder saveOrder) {
super("academicpages", "academic pages markdowns", StandardFileType.MARKDOWN);
this.lfFileName = "academicpages";
this.directory = "academicpages";
this.layoutPreferences = layoutPreferences;
this.saveOrder = saveOrder;
String consoleName = "academicpages";
this.academicPagesTemplate = new TemplateExporter("academicpages", consoleName, lfFileName, directory, StandardFileType.MARKDOWN, layoutPreferences, saveOrder);
}

@Override
public void export(@NonNull final BibDatabaseContext databaseContext,
final Path exportDirectory,
@NonNull List<BibEntry> entries) throws SaveException {
export(databaseContext, exportDirectory, entries, List.of(), JournalAbbreviationLoader.loadBuiltInRepository());
}

/**
* The method that performs the export of all entries by iterating on the entries.
*
* @param databaseContext the database to export from
* @param file the directory to write to
* @param entries a list containing all entries that should be exported
* @param abbreviationRepository the built-in repository
* @throws SaveException Exception thrown if saving goes wrong
*/
@Override
public void export(@NonNull final BibDatabaseContext databaseContext,
final Path file,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sure that Path may be null?

Annoate all or nothing.

Proposal: Add @NullMarked to the class and mark only things which might be null - I think, there aren't any

@NonNull List<BibEntry> entries,
List<Path> fileDirForDataBase,
JournalAbbreviationRepository abbreviationRepository) throws SaveException {
if (entries.isEmpty()) { // Only export if entries exist
return;
}
try {
// convert what the ExportCommand gives as a file parameter to a directory
Path baseDir = file;
String exportDirectoryString = FileUtil.getBaseName(file);
Path exportDirectory = baseDir.getParent().resolve(exportDirectoryString);

// Ensure the directory exists. This is important: AtomicFileWriter will fail if parent dirs are missing.
Files.createDirectories(exportDirectory);

for (BibEntry entry : entries) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could simply switch this to a normal for loop with for (int i =1; i< entiries.length; i++) so you don't need the iterator variable.

if (entry.getType() == null) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wait, what? When can this happen?

LOGGER.warn("Skipping entry with no type: {}", entry);
continue;
}
// formatting the title of each entry to match the file names format demanded by academic pages (applying the same formatters applied to the title in the academicpages.layout)
Path path = getPath(entry, exportDirectory);

List<BibEntry> individual_entry = new ArrayList<>();
individual_entry.add(entry);
Comment on lines +103 to +104
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wait, what? Use List.of(entry) directly as parameter in the next line.

academicPagesTemplate.export(databaseContext, path, individual_entry, fileDirForDataBase, abbreviationRepository);
}
} catch (IOException e) {
throw new SaveException("could not export");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
throw new SaveException("could not export");
throw new SaveException("could not export", e);

}
}

private static @NonNull Path getPath(BibEntry entry, Path exportDirectory) {
Replace replace_formatter = new Replace();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why underscores in varable names? In Java, it is camel case.

replace_formatter.setArgument(" ,-");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thsi is a magic constant - please add a comment why this strange argument.

RemoveLatexCommandsFormatter commands_formatter = new RemoveLatexCommandsFormatter();
HTMLChars html_formatter = new HTMLChars();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add all formatters as class variable

String title = entry.getTitle().get();
String formatted_title = commands_formatter.format(html_formatter.format(replace_formatter.format(title)));
SafeFileName safe_formatter = new SafeFileName(); // added custom formatter to remove all characters that are not allowed in filenames
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why? It is obvious - then remove the comment.

String safe_title = safe_formatter.format(formatted_title);
return exportDirectory.resolve(safe_title + ".md");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ public static ExporterFactory create(CliPreferences preferences) {
exporters.add(new EmbeddedBibFilePdfExporter(bibDatabaseMode, preferences.getCustomEntryTypesRepository(), fieldPreferences));
exporters.add(new CffExporter());
exporters.add(new EndnoteXmlExporter(preferences.getBibEntryPreferences()));
exporters.add(new AcademicPagesExporter(layoutPreferences, saveOrder));

// Now add custom export formats
exporters.addAll(customFormats);
Expand Down
6 changes: 6 additions & 0 deletions jablib/src/main/java/org/jabref/logic/layout/LayoutEntry.java
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
import org.jabref.logic.layout.format.NonSpaceWhitespaceRemover;
import org.jabref.logic.layout.format.NotFoundFormatter;
import org.jabref.logic.layout.format.Number;
import org.jabref.logic.layout.format.NumberMonthFormatter;
import org.jabref.logic.layout.format.Ordinal;
import org.jabref.logic.layout.format.RTFChars;
import org.jabref.logic.layout.format.RemoveBrackets;
Expand All @@ -77,6 +78,7 @@
import org.jabref.logic.layout.format.RisAuthors;
import org.jabref.logic.layout.format.RisKeywords;
import org.jabref.logic.layout.format.RisMonth;
import org.jabref.logic.layout.format.SafeFileName;
import org.jabref.logic.layout.format.ShortMonthFormatter;
import org.jabref.logic.layout.format.ToLowerCase;
import org.jabref.logic.layout.format.ToUpperCase;
Expand Down Expand Up @@ -565,6 +567,10 @@ private LayoutFormatter getLayoutFormatterByName(String name) {
new ReplaceWithEscapedDoubleQuotes();
case "HayagrivaType" ->
new HayagrivaType();
case "NumberMonth" ->
new NumberMonthFormatter();
case "SafeFileName" ->
new SafeFileName();
default ->
null;
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package org.jabref.logic.layout.format;

import java.util.Optional;

import org.jabref.logic.layout.LayoutFormatter;
import org.jabref.model.entry.Month;

/**
* Convert the month name into the corresponding number and return 01 by default
*/
public class NumberMonthFormatter implements LayoutFormatter {

@Override
public String format(String fieldText) {
Optional<Month> month = Month.parse(fieldText);
return month.map(Month::getTwoDigitNumber).orElse("01");
Comment on lines +15 to +16
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Merge this into one line plese.

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package org.jabref.logic.layout.format;

import org.jabref.logic.layout.LayoutFormatter;

/**
* Remove all the characters that are not allowed by the OS in file names
*/
public class SafeFileName implements LayoutFormatter {

@Override
public String format(String fieldText) {
return fieldText.replaceAll("[\\\\/:*?\"<>|]", "");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
title: "\format[RemoveLatexCommands,HTMLChars]{\title}"
collection: publications
category: \format{\entrytype}
permalink: /publication/\format[RemoveLatexCommands,HTMLChars,Replace(\s,-),SafeFileName]{\title}
excerpt: '\begin{note}\format[RemoveLatexCommands,HTMLChars]{\note}\end{note}'
date: \format{\year}-\begin{month}\format[NumberMonth]{\month}\end{month}\begin{!month}01\end{!month}-\begin{day}\format{\day}\end{day}\begin{!day}01\end{!day}
venue: '\format[RemoveLatexCommands,HTMLChars]{\journal}\begin{!journal}Unknown\end{!journal}'
slidesurl: '\begin{file}\format[FileLink(pdf)]{\file}\end{file}\begin{!file}https://[insert username].github.io/files/[insert filename].pdf\end{!file}'
paperurl: '\begin{file}\format[FileLink(pdf)]{\file}\end{file}\begin{!file}https://[insert username].github.io/files/[insert filename].pdf\end{!file}'
bibtexurl: 'https://[insert username].github.io/files/[insert filename].bib'
citation: '\format[HTMLChars]{\author}. (\format{\year}). "&quot;\format[RemoveLatexCommands,HTMLChars]{\title}.&quot; <i>\format[RemoveLatexCommands,HTMLChars]{\journal}</i>.'
---
\begin{abstract}\format{\abstract}\end{abstract}
Loading