diff --git a/CHANGELOG.md b/CHANGELOG.md
index fe7c548e02f..355c620c2b1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -14,12 +14,14 @@ Note that this project **does not** adhere to [Semantic Versioning](http://semve
### Changed
- We integrated the external file types dialog directly inside the preferences. [#8341](https://github.com/JabRef/jabref/pull/8341)
+- We inverted the logic for resolving [BibTeX strings](https://docs.jabref.org/advanced/strings). This helps to keep `#` chars. By default String resolving is only activated for a couple of standard fields. The list of fields can be modified in the preferences. [#7010](https://github.com/JabRef/jabref/issues/7010), [#7102](https://github.com/JabRef/jabref/issues/7012), [#8303](https://github.com/JabRef/jabref/issues/8303)
- We moved the search box in preview preferences closer to the available citation styles list. [#8370](https://github.com/JabRef/jabref/pull/8370)
- Changing the preference to show the preview panel as a separate tab now has effect without restarting JabRef. [#8370](https://github.com/JabRef/jabref/pull/8370)
- We enabled switching themes in JabRef without the need to restart JabRef. [#7335](https://github.com/JabRef/jabref/pull/7335)
### Fixed
+- We fixed an issue where `#`chars in certain fields would be interpreted as BibTeX strings [#7010](https://github.com/JabRef/jabref/issues/7010), [#7102](https://github.com/JabRef/jabref/issues/7012), [#8303](https://github.com/JabRef/jabref/issues/8303)
- We fixed an issue where the fulltext search on an empty library with no documents would lead to an exception [koppor#522](https://github.com/koppor/jabref/issues/522)
- We fixed an issue where clicking on "Accept changes" in the merge dialog would lead to an exception [forum#2418](https://discourse.jabref.org/t/the-library-has-been-modified-by-another-program/2418/8)
- We fixed an issue where clicking on headings in the entry preview could lead to an exception. [#8292](https://github.com/JabRef/jabref/issues/8292)
diff --git a/docs/adr.md b/docs/adr.md
index cd80bb6457c..856d60a72b9 100644
--- a/docs/adr.md
+++ b/docs/adr.md
@@ -21,10 +21,11 @@ Architectural decisions for JabRef:
* [ADR-0016](https://github.com/JabRef/jabref/tree/main/docs/adr/0016-mutable-preferences-objects.md) - Mutable preferences objects
* [ADR-0017](https://github.com/JabRef/jabref/tree/main/docs/adr/0017-allow-model-access-logic.md) - Allow org.jabref.model to access org.jabref.logic
* [ADR-0018](https://github.com/JabRef/jabref/blob/main/docs/adr/0018-use-regular-expression-to-split-multiple-sentence-titles.md) - Use regular expression to split multiple-sentence titles
-* [ADR-0019](https://github.com/JabRef/jabref/blob/main/docs/adr/0019-implement-special-fields-as-seperate-fields.md) - Implement special fields as seperate fields
+* [ADR-0019](https://github.com/JabRef/jabref/blob/main/docs/adr/0019-implement-special-fields-as-seperate-fields.md) - Implement special fields as separate fields
* [ADR-0020](https://github.com/JabRef/jabref/blob/main/docs/adr/0020-use-Jackson-to-parse-study-yml.md) - Use Jackson to parse study.yml
* [ADR-0021](https://github.com/JabRef/jabref/blob/main/docs/adr/0021-keep-study-as-a-dto.md) - Keep study as a DTO
* [ADR-0022](https://github.com/JabRef/jabref/blob/main/docs/adr/0022-remove-stop-words-during-query-transformation.md) - Remove stop words during query transformation
* [ADR-0023](https://github.com/JabRef/jabref/blob/main/docs/adr/0023-localized-preferences.md) - Localized Preferences
+* [ADR-0024](https://github.com/JabRef/jabref/blob/main/docs/adr/0024-use-#-as-indicator-for-BibTeX-string-constants.md) - Use `#` as indicator for BibTeX string constants
For new ADRs, please use [template.md](https://github.com/JabRef/jabref/tree/main/docs/adr/template.md) as basis. More information on the used format is available at [https://adr.github.io/madr/](https://adr.github.io/madr/). General information about architectural decision records is available at [https://adr.github.io/](https://adr.github.io/). Then add them to the above list.
diff --git a/docs/adr/0019-implement-special-fields-as-seperate-fields.md b/docs/adr/0019-implement-special-fields-as-separate-fields.md
similarity index 98%
rename from docs/adr/0019-implement-special-fields-as-seperate-fields.md
rename to docs/adr/0019-implement-special-fields-as-separate-fields.md
index 06ef4760e91..2083c9eb73b 100644
--- a/docs/adr/0019-implement-special-fields-as-seperate-fields.md
+++ b/docs/adr/0019-implement-special-fields-as-separate-fields.md
@@ -1,4 +1,4 @@
-# Implement special fields as seperate fields
+# Implement special fields as separate fields
## Context and Problem Statement
diff --git a/docs/adr/0024-use-#-as-indicator-for-BibTeX-string-constants.md b/docs/adr/0024-use-#-as-indicator-for-BibTeX-string-constants.md
new file mode 100644
index 00000000000..edeb27c150c
--- /dev/null
+++ b/docs/adr/0024-use-#-as-indicator-for-BibTeX-string-constants.md
@@ -0,0 +1,133 @@
+# Use `#` as indicator for BibTeX string constants
+
+Bibtex supports string constants. The entry editor should support that, too.
+Affected code is (at least) `org.jabref.logic.importer.fileformat.BibtexParser#parseFieldContent` and `org.jabref.logic.bibtex.FieldWriter#formatAndResolveStrings`
+
+## Decision Drivers
+
+* Full BibTeX compatibility
+* Intuitive for the user
+* UI backwards compatible
+
+## Considered Options
+
+* Wrap string constants in `#`
+* Replace the internal `#` in JabRef by the non-used character `§`
+* Replace the internal `#` in JabRef by the non-used character `%`
+* Replace the internal `#` in JabRef by the non-used character `&`
+* Replace the internal `#` in JabRef by a single `&`
+* Change the data type of a field value
+* Wrap plan # in curly braces: `{#}`
+
+## Decision Outcome
+
+Chosen option: "Wrap string constants in #", because already existing behavior
+
+## Pros and Cons of the Options
+
+### Wrap string constants in `#`
+
+When BibTeX on the disk contains `field = value`, it is rendered as `field = #value#` in the entry editor. The user then knows that `value` is a BibTeX string.
+
+Example:
+
+left: BibTeX; right: Entry Editor
+
+```text
+@String{ value = "example" }
+
+field1 = value -> #value#
+field2 = {value} -> value
+
+field1 = value # value --> #value# # #value#
+```
+
+* Good, because In place in JabRef since more than 10 years
+* Bad, because `#` is used in BibTeX for string concatenation
+* Bad, because `#` is used in Markdown to indicate headings. When using Markdown in fields such as comments, this causes writing errors
+* Bad, because `#` could appear in URLs
+
+### Replace the internal `#` in JabRef by the non-used character `§`
+
+When BibTeX on the disk contains `field = value`, it is rendered as `field = §value§` in the entry editor. The user then knows that `value` is a BibTeX string.
+
+Example:
+
+left: BibTeX; right: Entry Editor
+
+```text
+field1 = value -> §value§
+field2 = {value} -> value
+
+field1 = value # value --> §value§ # §value§
+```
+
+* Good, because Easy to implement
+* Good, because No conflict with BibTeX's `#` sign
+* Bad, because Documentation needs to be updated
+* Bad, because `§` is not available on an US keyboard
+
+### Replace the internal `#` in JabRef by the non-used character `%`
+
+Similar to "Replace the internal # in JabRef by the non-used character §"
+
+Example:
+
+left: BibTeX; right: Entry Editor
+
+```text
+field1 = value -> %value%
+field2 = {value} -> value
+
+field1 = value # value --> %value% # %value%
+```
+
+* Good, because A user does not write LaTeX comments inside a string
+* Bad, because `%` could be used in Markdown, too
+* Bad, because `%` is used for comments in LaTeX and thus migtht cause confusion
+* Bad, because `%` could appear in URLs: There is [url percent encoding](https://www.w3schools.com/tags/ref_urlencode.asp)
+
+### Replace the internal `#` in JabRef by the non-used character `&`
+
+Similar to "Replace the internal `#` in JabRef by the non-used character `§`"
+
+Example:
+
+left: BibTeX; right: Entry Editor
+
+```text
+field1 = value -> &value&
+field2 = {value} -> value
+
+field1 = value # value --> &value& # &value&
+```
+
+* Good, because Users do not write LaTeX tables
+* Bad, because `&` is a LaTeX command for tables
+
+### Replace the internal `#` in JabRef by a single `&`
+
+Prefix strings with `&`
+
+Example:
+
+left: BibTeX; right: Entry Editor
+
+```text
+field1 = value -> &value
+field2 = {value} -> value
+
+field1 = value # value --> &value # &value
+```
+
+* Good, because Near to C syntax
+* Bad, because `&` is a LaTeX command for tables
+* Bad, because `&` could appear in URLs
+
+### Change the data type of a field value
+
+`org.jabref.model.entry.BibEntry#setField(org.jabref.model.entry.field.Field, java.lang.String)` changes to `org.jabref.model.entry.BibEntry#setField(org.jabref.model.entry.field.Field, org.jabref.model.entry.field.Value)` (org.jabref.model.entry.BibEntry#setField(org.jabref.model.entry.field.Field, java.lang.String)). This would bring JabRef's internal data model even more close to BibTeX
+
+* Good, because More object-orientated design of BibTeX field storage
+* Good, because Easies implementation of an advanced field editor
+* Bad, because High effort to implement
diff --git a/src/main/java/org/jabref/gui/preferences/file/FileTab.fxml b/src/main/java/org/jabref/gui/preferences/file/FileTab.fxml
index 8cc56872d65..b85c021f419 100644
--- a/src/main/java/org/jabref/gui/preferences/file/FileTab.fxml
+++ b/src/main/java/org/jabref/gui/preferences/file/FileTab.fxml
@@ -1,9 +1,7 @@
-
-
@@ -15,27 +13,34 @@
xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml"
fx:controller="org.jabref.gui.preferences.file.FileTab">
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
diff --git a/src/main/java/org/jabref/gui/preferences/file/FileTab.java b/src/main/java/org/jabref/gui/preferences/file/FileTab.java
index d6877b57c20..6148a5b5066 100644
--- a/src/main/java/org/jabref/gui/preferences/file/FileTab.java
+++ b/src/main/java/org/jabref/gui/preferences/file/FileTab.java
@@ -21,9 +21,9 @@ public class FileTab extends AbstractPreferenceTabView impleme
@FXML private CheckBox openLastStartup;
@FXML private TextField noWrapFiles;
- @FXML private RadioButton resolveStringsBibTex;
- @FXML private RadioButton resolveStringsAll;
- @FXML private TextField resolveStringsExcept;
+ @FXML private RadioButton doNotResolveStrings;
+ @FXML private RadioButton resolveStrings;
+ @FXML private TextField resolveStringsForFields;
@FXML private CheckBox alwaysReformatBib;
@FXML private CheckBox autosaveLocalLibraries;
@@ -39,12 +39,13 @@ public void initialize() {
this.viewModel = new FileTabViewModel(preferencesService);
openLastStartup.selectedProperty().bindBidirectional(viewModel.openLastStartupProperty());
noWrapFiles.textProperty().bindBidirectional(viewModel.noWrapFilesProperty());
- resolveStringsBibTex.selectedProperty().bindBidirectional(viewModel.resolveStringsBibTexProperty());
- resolveStringsAll.selectedProperty().bindBidirectional(viewModel.resolveStringsAllProperty());
- resolveStringsExcept.textProperty().bindBidirectional(viewModel.resolveStringsExceptProperty());
- resolveStringsExcept.disableProperty().bind(resolveStringsAll.selectedProperty().not());
- alwaysReformatBib.selectedProperty().bindBidirectional(viewModel.alwaysReformatBibProperty());
+ doNotResolveStrings.selectedProperty().bindBidirectional(viewModel.doNotResolveStringsProperty());
+ resolveStrings.selectedProperty().bindBidirectional(viewModel.resolveStringsProperty());
+ resolveStringsForFields.textProperty().bindBidirectional(viewModel.resolveStringsForFieldsProperty());
+ resolveStringsForFields.disableProperty().bind(doNotResolveStrings.selectedProperty());
+
+ alwaysReformatBib.selectedProperty().bindBidirectional(viewModel.alwaysReformatBibProperty());
autosaveLocalLibraries.selectedProperty().bindBidirectional(viewModel.autosaveLocalLibrariesProperty());
ActionFactory actionFactory = new ActionFactory(Globals.getKeyPrefs());
diff --git a/src/main/java/org/jabref/gui/preferences/file/FileTabViewModel.java b/src/main/java/org/jabref/gui/preferences/file/FileTabViewModel.java
index 65a26ecf342..e6885febd1e 100644
--- a/src/main/java/org/jabref/gui/preferences/file/FileTabViewModel.java
+++ b/src/main/java/org/jabref/gui/preferences/file/FileTabViewModel.java
@@ -13,9 +13,9 @@ public class FileTabViewModel implements PreferenceTabViewModel {
private final BooleanProperty openLastStartupProperty = new SimpleBooleanProperty();
private final StringProperty noWrapFilesProperty = new SimpleStringProperty("");
- private final BooleanProperty resolveStringsBibTexProperty = new SimpleBooleanProperty();
- private final BooleanProperty resolveStringsAllProperty = new SimpleBooleanProperty();
- private final StringProperty resolveStringsExceptProperty = new SimpleStringProperty("");
+ private final BooleanProperty doNotResolveStringsProperty = new SimpleBooleanProperty();
+ private final BooleanProperty resolveStringsProperty = new SimpleBooleanProperty();
+ private final StringProperty resolveStringsForFieldsProperty = new SimpleStringProperty("");
private final BooleanProperty alwaysReformatBibProperty = new SimpleBooleanProperty();
private final BooleanProperty autosaveLocalLibraries = new SimpleBooleanProperty();
@@ -30,14 +30,12 @@ public class FileTabViewModel implements PreferenceTabViewModel {
@Override
public void setValues() {
openLastStartupProperty.setValue(preferences.shouldOpenLastFilesOnStartup());
-
noWrapFilesProperty.setValue(importExportPreferences.getNonWrappableFields());
- resolveStringsAllProperty.setValue(importExportPreferences.shouldResolveStringsForAllStrings()); // Flipped around
- resolveStringsBibTexProperty.setValue(importExportPreferences.shouldResolveStringsForStandardBibtexFields());
- resolveStringsExceptProperty.setValue(importExportPreferences.getNonResolvableFields());
+ doNotResolveStringsProperty.setValue(!importExportPreferences.resolveStrings());
+ resolveStringsProperty.setValue(importExportPreferences.resolveStrings());
+ resolveStringsForFieldsProperty.setValue(importExportPreferences.getResolvableFields());
alwaysReformatBibProperty.setValue(importExportPreferences.shouldAlwaysReformatOnSave());
-
autosaveLocalLibraries.setValue(preferences.shouldAutosave());
}
@@ -45,10 +43,9 @@ public void setValues() {
public void storeSettings() {
preferences.storeOpenLastFilesOnStartup(openLastStartupProperty.getValue());
+ importExportPreferences.setResolveStrings(!doNotResolveStringsProperty.getValue());
importExportPreferences.setNonWrappableFields(noWrapFilesProperty.getValue().trim());
- importExportPreferences.setResolveStringsForStandardBibtexFields(resolveStringsBibTexProperty.getValue());
- importExportPreferences.setResolveStringsForAllStrings(resolveStringsAllProperty.getValue());
- importExportPreferences.setNonResolvableFields(resolveStringsExceptProperty.getValue().trim());
+ importExportPreferences.setResolvableFields(resolveStringsForFieldsProperty.getValue().trim());
importExportPreferences.setAlwaysReformatOnSave(alwaysReformatBibProperty.getValue());
preferences.storeShouldAutosave(autosaveLocalLibraries.getValue());
@@ -66,16 +63,16 @@ public StringProperty noWrapFilesProperty() {
return noWrapFilesProperty;
}
- public BooleanProperty resolveStringsBibTexProperty() {
- return resolveStringsBibTexProperty;
+ public BooleanProperty doNotResolveStringsProperty() {
+ return doNotResolveStringsProperty;
}
- public BooleanProperty resolveStringsAllProperty() {
- return resolveStringsAllProperty;
+ public BooleanProperty resolveStringsProperty() {
+ return resolveStringsProperty;
}
- public StringProperty resolveStringsExceptProperty() {
- return resolveStringsExceptProperty;
+ public StringProperty resolveStringsForFieldsProperty() {
+ return resolveStringsForFieldsProperty;
}
public BooleanProperty alwaysReformatBibProperty() {
diff --git a/src/main/java/org/jabref/logic/bibtex/FieldWriter.java b/src/main/java/org/jabref/logic/bibtex/FieldWriter.java
index 4e826ccd5dc..a917fd116e9 100644
--- a/src/main/java/org/jabref/logic/bibtex/FieldWriter.java
+++ b/src/main/java/org/jabref/logic/bibtex/FieldWriter.java
@@ -2,8 +2,6 @@
import org.jabref.logic.util.OS;
import org.jabref.model.entry.field.Field;
-import org.jabref.model.entry.field.InternalField;
-import org.jabref.model.entry.field.StandardField;
import org.jabref.model.strings.StringUtil;
import org.slf4j.Logger;
@@ -14,6 +12,9 @@
*/
public class FieldWriter {
+ // See also ADR-0024
+ public static final char BIBTEX_STRING_START_END_SYMBOL = '#';
+
private static final Logger LOGGER = LoggerFactory.getLogger(FieldWriter.class);
private static final char FIELD_START = '{';
@@ -86,7 +87,6 @@ public String write(Field field, String content) throws InvalidFieldValueExcepti
return FIELD_START + String.valueOf(FIELD_END);
}
- // If the field is non-standard, we will just append braces, wrap and write.
if (!shouldResolveStrings(field)) {
return formatWithoutResolvingStrings(content, field);
}
@@ -113,7 +113,7 @@ private String formatAndResolveStrings(String content, Field field) throws Inval
int goFrom = pivot;
int pos1 = pivot;
while (goFrom == pos1) {
- pos1 = content.indexOf('#', goFrom);
+ pos1 = content.indexOf(BIBTEX_STRING_START_END_SYMBOL, goFrom);
if ((pos1 > 0) && (content.charAt(pos1 - 1) == '\\')) {
goFrom = pos1 + 1;
pos1++;
@@ -127,16 +127,19 @@ private String formatAndResolveStrings(String content, Field field) throws Inval
pos1 = content.length(); // No more occurrences found.
pos2 = -1;
} else {
- pos2 = content.indexOf('#', pos1 + 1);
+ pos2 = content.indexOf(BIBTEX_STRING_START_END_SYMBOL, pos1 + 1);
if (pos2 == -1) {
if (neverFailOnHashes) {
pos1 = content.length(); // just write out the rest of the text, and throw no exception
} else {
- LOGGER.error("The # character is not allowed in BibTeX strings unless escaped as in '\\#'. "
+ LOGGER.error("The character {} is not allowed in BibTeX strings unless escaped as in '\\{}'. "
+ "In JabRef, use pairs of # characters to indicate a string. "
- + "Note that the entry causing the problem has been selected. Field value: {}", content);
+ + "Note that the entry causing the problem has been selected. Field value: {}",
+ BIBTEX_STRING_START_END_SYMBOL,
+ BIBTEX_STRING_START_END_SYMBOL,
+ content);
throw new InvalidFieldValueException(
- "The # character is not allowed in BibTeX strings unless escaped as in '\\#'.\n"
+ "The character " + BIBTEX_STRING_START_END_SYMBOL + " is not allowed in BibTeX strings unless escaped as in '\\" + BIBTEX_STRING_START_END_SYMBOL + "'.\n"
+ "In JabRef, use pairs of # characters to indicate a string.\n"
+ "Note that the entry causing the problem has been selected. Field value: " + content);
}
@@ -165,13 +168,11 @@ private String formatAndResolveStrings(String content, Field field) throws Inval
}
private boolean shouldResolveStrings(Field field) {
- if (preferences.isResolveStringsAllFields()) {
- // Resolve strings for all fields except some:
- return !preferences.getDoNotResolveStringsFor().contains(field);
- } else {
- // Default operation - we only resolve strings for standard fields:
- return field instanceof StandardField || InternalField.BIBTEX_STRING.equals(field);
+ if (preferences.isResolveStrings()) {
+ // Resolve strings for the list of fields only
+ return preferences.getResolveStringsForFields().contains(field);
}
+ return false;
}
private String formatWithoutResolvingStrings(String content, Field field) throws InvalidFieldValueException {
diff --git a/src/main/java/org/jabref/logic/bibtex/FieldWriterPreferences.java b/src/main/java/org/jabref/logic/bibtex/FieldWriterPreferences.java
index 51654c788a8..b153ef1a547 100644
--- a/src/main/java/org/jabref/logic/bibtex/FieldWriterPreferences.java
+++ b/src/main/java/org/jabref/logic/bibtex/FieldWriterPreferences.java
@@ -1,39 +1,32 @@
package org.jabref.logic.bibtex;
-import java.util.Collections;
import java.util.List;
import org.jabref.model.entry.field.Field;
public class FieldWriterPreferences {
- private final boolean resolveStringsAllFields;
- private final List doNotResolveStringsFor;
+ private final boolean resolveStrings;
+ private final List resolveStringsForFields;
private final int lineLength = 65; // Constant
private final FieldContentFormatterPreferences fieldContentFormatterPreferences;
- public FieldWriterPreferences(boolean resolveStringsAllFields, List doNotResolveStringsFor,
- FieldContentFormatterPreferences fieldContentFormatterPreferences) {
- this.resolveStringsAllFields = resolveStringsAllFields;
- this.doNotResolveStringsFor = doNotResolveStringsFor;
- this.fieldContentFormatterPreferences = fieldContentFormatterPreferences;
- }
-
/**
- * Creates an instance with default values (not obeying any user preferences). This constructor should be used with
- * caution. The other constructor has to be preferred.
+ * @param resolveStrings true - The character {@link FieldWriter#BIBTEX_STRING_START_END_SYMBOL} should be interpreted as indicator of BibTeX strings
*/
- public FieldWriterPreferences() {
- // This constructor is only to allow an empty constructor in SavePreferences
- this(true, Collections.emptyList(), new FieldContentFormatterPreferences());
+ public FieldWriterPreferences(boolean resolveStrings, List resolveStringsForFields,
+ FieldContentFormatterPreferences fieldContentFormatterPreferences) {
+ this.resolveStrings = resolveStrings;
+ this.resolveStringsForFields = resolveStringsForFields;
+ this.fieldContentFormatterPreferences = fieldContentFormatterPreferences;
}
- public boolean isResolveStringsAllFields() {
- return resolveStringsAllFields;
+ public boolean isResolveStrings() {
+ return resolveStrings;
}
- public List getDoNotResolveStringsFor() {
- return doNotResolveStringsFor;
+ public List getResolveStringsForFields() {
+ return resolveStringsForFields;
}
public int getLineLength() {
diff --git a/src/main/java/org/jabref/logic/bst/VM.java b/src/main/java/org/jabref/logic/bst/VM.java
index 5e99a62b12c..eab8f4003a2 100644
--- a/src/main/java/org/jabref/logic/bst/VM.java
+++ b/src/main/java/org/jabref/logic/bst/VM.java
@@ -14,6 +14,7 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import org.jabref.logic.bibtex.FieldContentFormatterPreferences;
import org.jabref.logic.bibtex.FieldWriter;
import org.jabref.logic.bibtex.FieldWriterPreferences;
import org.jabref.logic.bibtex.InvalidFieldValueException;
@@ -927,7 +928,7 @@ public String run(Collection bibEntries, BibDatabase bibDatabase) {
* @param bibDatabase
*/
private void read(BibDatabase bibDatabase) {
- FieldWriter fieldWriter = new FieldWriter(new FieldWriterPreferences());
+ FieldWriter fieldWriter = new FieldWriter(new FieldWriterPreferences(true, List.of(StandardField.MONTH), new FieldContentFormatterPreferences()));
for (BstEntry e : entries) {
for (Map.Entry mEntry : e.fields.entrySet()) {
Field field = FieldFactory.parseField(mEntry.getKey());
diff --git a/src/main/java/org/jabref/logic/importer/fileformat/BibtexParser.java b/src/main/java/org/jabref/logic/importer/fileformat/BibtexParser.java
index 84091cfa47d..b2bc701cb87 100644
--- a/src/main/java/org/jabref/logic/importer/fileformat/BibtexParser.java
+++ b/src/main/java/org/jabref/logic/importer/fileformat/BibtexParser.java
@@ -22,6 +22,7 @@
import java.util.regex.Pattern;
import org.jabref.logic.bibtex.FieldContentFormatter;
+import org.jabref.logic.bibtex.FieldWriter;
import org.jabref.logic.exporter.BibtexDatabaseWriter;
import org.jabref.logic.exporter.SavePreferences;
import org.jabref.logic.importer.ImportFormatPreferences;
@@ -641,6 +642,9 @@ private String parseFieldContent(Field field) throws IOException {
String number = parseTextToken();
value.append(number);
} else if (character == '#') {
+ // Here, we hit the case of BibTeX string concatenation. E.g., "author = Kopp # Kolb".
+ // We did NOT hit org.jabref.logic.bibtex.FieldWriter#BIBTEX_STRING_START_END_SYMBOL
+ // See also ADR-0024
consume('#');
} else {
String textToken = parseTextToken();
@@ -648,7 +652,7 @@ private String parseFieldContent(Field field) throws IOException {
throw new IOException("Error in line " + line + " or above: "
+ "Empty text token.\nThis could be caused " + "by a missing comma between two fields.");
}
- value.append('#').append(textToken).append('#');
+ value.append(FieldWriter.BIBTEX_STRING_START_END_SYMBOL).append(textToken).append(FieldWriter.BIBTEX_STRING_START_END_SYMBOL);
}
skipWhitespace();
}
diff --git a/src/main/java/org/jabref/logic/integrity/BibStringChecker.java b/src/main/java/org/jabref/logic/integrity/BibStringChecker.java
index acae104f885..567094d868e 100644
--- a/src/main/java/org/jabref/logic/integrity/BibStringChecker.java
+++ b/src/main/java/org/jabref/logic/integrity/BibStringChecker.java
@@ -6,18 +6,19 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import org.jabref.logic.bibtex.FieldWriter;
import org.jabref.logic.l10n.Localization;
import org.jabref.model.entry.BibEntry;
import org.jabref.model.entry.field.Field;
import org.jabref.model.entry.field.FieldProperty;
/**
- * Checks, if there is an even number of unescaped #
+ * Checks, if there is an even number of unescaped # (FieldWriter.BIBTEX_STRING_START_END_SYMBOL)
*/
public class BibStringChecker implements EntryChecker {
- // Detect # if it doesn't have a \ in front of it or if it starts the string
- private static final Pattern UNESCAPED_HASH = Pattern.compile("(? check(BibEntry entry) {
@@ -33,6 +34,7 @@ public List check(BibEntry entry) {
hashCount++;
}
if ((hashCount & 1) == 1) { // Check if odd
+ // # is FieldWriter.BIBTEX_STRING_START_END_SYMBOL
results.add(new IntegrityMessage(Localization.lang("odd number of unescaped '#'"), entry,
field.getKey()));
}
diff --git a/src/main/java/org/jabref/model/database/BibDatabase.java b/src/main/java/org/jabref/model/database/BibDatabase.java
index 1fdb22ee890..14193a0d14e 100644
--- a/src/main/java/org/jabref/model/database/BibDatabase.java
+++ b/src/main/java/org/jabref/model/database/BibDatabase.java
@@ -21,6 +21,7 @@
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
+import org.jabref.logic.bibtex.FieldWriter;
import org.jabref.model.database.event.EntriesAddedEvent;
import org.jabref.model.database.event.EntriesRemovedEvent;
import org.jabref.model.entry.BibEntry;
@@ -502,14 +503,14 @@ private String resolveContent(String result, Set usedIds, Set al
StringBuilder newRes = new StringBuilder();
int piv = 0;
int next;
- while ((next = res.indexOf('#', piv)) >= 0) {
+ while ((next = res.indexOf(FieldWriter.BIBTEX_STRING_START_END_SYMBOL, piv)) >= 0) {
// We found the next string ref. Append the text
// up to it.
if (next > 0) {
newRes.append(res, piv, next);
}
- int stringEnd = res.indexOf('#', next + 1);
+ int stringEnd = res.indexOf(FieldWriter.BIBTEX_STRING_START_END_SYMBOL, next + 1);
if (stringEnd >= 0) {
// We found the boundaries of the string ref,
// now resolve that one.
diff --git a/src/main/java/org/jabref/model/entry/Month.java b/src/main/java/org/jabref/model/entry/Month.java
index e079ab8c1a9..85db2fd802d 100644
--- a/src/main/java/org/jabref/model/entry/Month.java
+++ b/src/main/java/org/jabref/model/entry/Month.java
@@ -2,6 +2,7 @@
import java.util.Optional;
+import org.jabref.logic.bibtex.FieldWriter;
import org.jabref.model.strings.StringUtil;
/**
@@ -165,7 +166,7 @@ public String getShortName() {
}
/**
- * Returns the month in JabRef format. The format is the short 3-digit name surrounded by a '#'.
+ * Returns the month in JabRef format. The format is the short 3-digit name surrounded by a '#' (FieldWriter.BIBTEX_STRING_START_END_SYMBOL).
* Example: #jan#, #feb#, etc.
*
* See Issue 263 for a discussion on that thing.
@@ -175,7 +176,7 @@ public String getShortName() {
* @return Month in JabRef format
*/
public String getJabRefFormat() {
- return String.format("#%s#", shortName);
+ return String.format(FieldWriter.BIBTEX_STRING_START_END_SYMBOL + "%s" + FieldWriter.BIBTEX_STRING_START_END_SYMBOL, shortName);
}
/**
diff --git a/src/main/java/org/jabref/model/strings/StringUtil.java b/src/main/java/org/jabref/model/strings/StringUtil.java
index 47c4158e5b9..c3f9e53a0fc 100644
--- a/src/main/java/org/jabref/model/strings/StringUtil.java
+++ b/src/main/java/org/jabref/model/strings/StringUtil.java
@@ -12,6 +12,7 @@
import java.util.regex.Pattern;
import org.jabref.architecture.ApacheCommonsLang3Allowed;
+import org.jabref.logic.bibtex.FieldWriter;
import com.google.common.base.CharMatcher;
import org.apache.commons.lang3.StringUtils;
@@ -323,7 +324,7 @@ public static String putBracesAroundCapitals(String s) {
inBrace++;
} else if (c == '}') {
inBrace--;
- } else if (!escaped && (c == '#')) {
+ } else if (!escaped && (c == FieldWriter.BIBTEX_STRING_START_END_SYMBOL)) {
inString = !inString;
}
diff --git a/src/main/java/org/jabref/preferences/ImportExportPreferences.java b/src/main/java/org/jabref/preferences/ImportExportPreferences.java
index a8a8d8a4389..03843fbb6e7 100644
--- a/src/main/java/org/jabref/preferences/ImportExportPreferences.java
+++ b/src/main/java/org/jabref/preferences/ImportExportPreferences.java
@@ -10,27 +10,25 @@
import javafx.beans.property.StringProperty;
public class ImportExportPreferences {
+
private final StringProperty nonWrappableFields;
- private final BooleanProperty resolveStringsForStandardBibtexFields;
- private final BooleanProperty resolveStringsForAllStrings;
- private final StringProperty nonResolvableFields;
+ private final BooleanProperty resolveStrings;
+ private final StringProperty resolvableFields;
private final BooleanProperty alwaysReformatOnSave;
private final ObjectProperty importWorkingDirectory;
private final StringProperty lastExportExtension;
private final ObjectProperty exportWorkingDirectory;
public ImportExportPreferences(String nonWrappableFields,
- boolean resolveStringsForStandardBibtexFields,
- boolean resolveStringsForAllStrings,
- String nonResolvableFields,
+ boolean resolveStrings,
+ String resolvableFields,
boolean alwaysReformatOnSave,
Path importWorkingDirectory,
String lastExportExtension,
Path exportWorkingDirectory) {
this.nonWrappableFields = new SimpleStringProperty(nonWrappableFields);
- this.resolveStringsForStandardBibtexFields = new SimpleBooleanProperty(resolveStringsForStandardBibtexFields);
- this.resolveStringsForAllStrings = new SimpleBooleanProperty(resolveStringsForAllStrings);
- this.nonResolvableFields = new SimpleStringProperty(nonResolvableFields);
+ this.resolveStrings = new SimpleBooleanProperty(resolveStrings);
+ this.resolvableFields = new SimpleStringProperty(resolvableFields);
this.alwaysReformatOnSave = new SimpleBooleanProperty(alwaysReformatOnSave);
this.importWorkingDirectory = new SimpleObjectProperty<>(importWorkingDirectory);
this.lastExportExtension = new SimpleStringProperty(lastExportExtension);
@@ -49,40 +47,28 @@ public void setNonWrappableFields(String nonWrappableFields) {
this.nonWrappableFields.set(nonWrappableFields);
}
- public boolean shouldResolveStringsForStandardBibtexFields() {
- return resolveStringsForStandardBibtexFields.get();
- }
-
- public BooleanProperty resolveStringsForStandardBibtexFieldsProperty() {
- return resolveStringsForStandardBibtexFields;
- }
-
- public void setResolveStringsForStandardBibtexFields(boolean resolveStringsForStandardBibtexFields) {
- this.resolveStringsForStandardBibtexFields.set(resolveStringsForStandardBibtexFields);
- }
-
- public boolean shouldResolveStringsForAllStrings() {
- return resolveStringsForAllStrings.get();
+ public boolean resolveStrings() {
+ return resolveStrings.get();
}
- public BooleanProperty resolveStringsForAllStringsProperty() {
- return resolveStringsForAllStrings;
+ public BooleanProperty resolveStringsProperty() {
+ return resolveStrings;
}
- public void setResolveStringsForAllStrings(boolean resolveStringsForAllStrings) {
- this.resolveStringsForAllStrings.set(resolveStringsForAllStrings);
+ public void setResolveStrings(boolean resolveStrings) {
+ this.resolveStrings.set(resolveStrings);
}
- public String getNonResolvableFields() {
- return nonResolvableFields.get();
+ public String getResolvableFields() {
+ return resolvableFields.get();
}
- public StringProperty nonResolvableFieldsProperty() {
- return nonResolvableFields;
+ public StringProperty resolvableFieldsProperty() {
+ return resolvableFields;
}
- public void setNonResolvableFields(String nonResolvableFields) {
- this.nonResolvableFields.set(nonResolvableFields);
+ public void setResolvableFields(String resolvableFields) {
+ this.resolvableFields.set(resolvableFields);
}
public boolean shouldAlwaysReformatOnSave() {
@@ -132,4 +118,5 @@ public ObjectProperty exportWorkingDirectoryProperty() {
public void setExportWorkingDirectory(Path exportWorkingDirectory) {
this.exportWorkingDirectory.set(exportWorkingDirectory);
}
+
}
diff --git a/src/main/java/org/jabref/preferences/JabRefPreferences.java b/src/main/java/org/jabref/preferences/JabRefPreferences.java
index d3633976cc0..829a780dd73 100644
--- a/src/main/java/org/jabref/preferences/JabRefPreferences.java
+++ b/src/main/java/org/jabref/preferences/JabRefPreferences.java
@@ -225,8 +225,8 @@ public class JabRefPreferences implements PreferencesService {
public static final String WARN_ABOUT_DUPLICATES_IN_INSPECTION = "warnAboutDuplicatesInInspection";
public static final String NON_WRAPPABLE_FIELDS = "nonWrappableFields";
- public static final String RESOLVE_STRINGS_ALL_FIELDS = "resolveStringsAllFields";
- public static final String DO_NOT_RESOLVE_STRINGS_FOR = "doNotResolveStringsFor";
+ public static final String RESOLVE_STRINGS_FOR_FIELDS = "resolveStringsForFields";
+ public static final String DO_NOT_RESOLVE_STRINGS = "doNotResolveStrings";
public static final String MERGE_ENTRIES_DIFF_MODE = "mergeEntriesDiffMode";
public static final String CUSTOM_EXPORT_FORMAT = "customExportFormat";
public static final String CUSTOM_IMPORT_FORMAT = "customImportFormat";
@@ -629,8 +629,8 @@ private JabRefPreferences() {
defaults.put(CONFIRM_DELETE, Boolean.TRUE);
defaults.put(DEFAULT_CITATION_KEY_PATTERN, "[auth][year]");
defaults.put(UNWANTED_CITATION_KEY_CHARACTERS, "-`ʹ:!;?^+");
- defaults.put(DO_NOT_RESOLVE_STRINGS_FOR, StandardField.URL.getName());
- defaults.put(RESOLVE_STRINGS_ALL_FIELDS, Boolean.FALSE);
+ defaults.put(RESOLVE_STRINGS_FOR_FIELDS, "author;booktitle;editor;editora;editorb;editorc;institution;issuetitle;journal;journalsubtitle;journaltitle;mainsubtitle;month;publisher;shortauthor;shorteditor;subtitle;titleaddon");
+ defaults.put(DO_NOT_RESOLVE_STRINGS, Boolean.FALSE);
defaults.put(NON_WRAPPABLE_FIELDS, "pdf;ps;url;doi;file;isbn;issn");
defaults.put(WARN_ABOUT_DUPLICATES_IN_INSPECTION, Boolean.TRUE);
defaults.put(ADD_CREATION_DATE, Boolean.FALSE);
@@ -2182,8 +2182,8 @@ public FieldContentFormatterPreferences getFieldContentParserPreferences() {
@Override
public FieldWriterPreferences getFieldWriterPreferences() {
return new FieldWriterPreferences(
- getBoolean(RESOLVE_STRINGS_ALL_FIELDS),
- getStringList(DO_NOT_RESOLVE_STRINGS_FOR).stream().map(FieldFactory::parseField).collect(Collectors.toList()),
+ !getBoolean(DO_NOT_RESOLVE_STRINGS),
+ getStringList(RESOLVE_STRINGS_FOR_FIELDS).stream().map(FieldFactory::parseField).collect(Collectors.toList()),
getFieldContentParserPreferences());
}
@@ -2294,18 +2294,16 @@ public ImportExportPreferences getImportExportPreferences() {
importExportPreferences = new ImportExportPreferences(
get(NON_WRAPPABLE_FIELDS),
- !getBoolean(RESOLVE_STRINGS_ALL_FIELDS),
- getBoolean(RESOLVE_STRINGS_ALL_FIELDS),
- get(DO_NOT_RESOLVE_STRINGS_FOR),
+ !getBoolean(DO_NOT_RESOLVE_STRINGS),
+ get(RESOLVE_STRINGS_FOR_FIELDS),
getBoolean(REFORMAT_FILE_ON_SAVE_AND_EXPORT),
Path.of(get(IMPORT_WORKING_DIRECTORY)),
get(LAST_USED_EXPORT),
Path.of(get(EXPORT_WORKING_DIRECTORY)));
EasyBind.listen(importExportPreferences.nonWrappableFieldsProperty(), (obs, oldValue, newValue) -> put(NON_WRAPPABLE_FIELDS, newValue));
- EasyBind.listen(importExportPreferences.resolveStringsForStandardBibtexFieldsProperty(), (obs, oldValue, newValue) -> putBoolean(RESOLVE_STRINGS_ALL_FIELDS, newValue));
- EasyBind.listen(importExportPreferences.resolveStringsForAllStringsProperty(), (obs, oldValue, newValue) -> putBoolean(RESOLVE_STRINGS_ALL_FIELDS, newValue));
- EasyBind.listen(importExportPreferences.nonResolvableFieldsProperty(), (obs, oldValue, newValue) -> put(DO_NOT_RESOLVE_STRINGS_FOR, newValue));
+ EasyBind.listen(importExportPreferences.resolveStringsProperty(), (obs, oldValue, newValue) -> putBoolean(DO_NOT_RESOLVE_STRINGS, !newValue));
+ EasyBind.listen(importExportPreferences.resolvableFieldsProperty(), (obs, oldValue, newValue) -> put(RESOLVE_STRINGS_FOR_FIELDS, newValue));
EasyBind.listen(importExportPreferences.alwaysReformatOnSaveProperty(), (obs, oldValue, newValue) -> putBoolean(REFORMAT_FILE_ON_SAVE_AND_EXPORT, newValue));
EasyBind.listen(importExportPreferences.importWorkingDirectoryProperty(), (obs, oldValue, newValue) -> put(IMPORT_WORKING_DIRECTORY, newValue.toString()));
EasyBind.listen(importExportPreferences.lastExportExtensionProperty(), (obs, oldValue, newValue) -> put(LAST_USED_EXPORT, newValue));
diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties
index 51561772656..e5353305040 100644
--- a/src/main/resources/l10n/JabRef_en.properties
+++ b/src/main/resources/l10n/JabRef_en.properties
@@ -729,8 +729,8 @@ Replaces\ Unicode\ ligatures\ with\ their\ expanded\ form=Replaces Unicode ligat
Required\ fields=Required fields
-Resolve\ strings\ for\ all\ fields\ except=Resolve strings for all fields except
-Resolve\ strings\ for\ standard\ BibTeX\ fields\ only=Resolve strings for standard BibTeX fields only
+Do\ not\ resolve\ BibTeX\ strings=Do not resolve BibTeX strings
+Resolve\ BibTeX\ strings\ for\ the\ following\ fields=Resolve BibTeX strings for the following fields
resolved=resolved
@@ -744,6 +744,8 @@ Review=Review
Review\ changes=Review changes
Review\ Field\ Migration=Review Field Migration
+Loading=Loading
+
Save=Save
Save\ all\ finished.=Save all finished.
@@ -966,7 +968,6 @@ Move\ contents\ of\ a\ field\ into\ a\ field\ with\ a\ different\ name=Move cont
Cannot\ use\ port\ %0\ for\ remote\ operation;\ another\ application\ may\ be\ using\ it.\ Try\ specifying\ another\ port.=Cannot use port %0 for remote operation; another application may be using it. Try specifying another port.
Looking\ for\ full\ text\ document...=Looking for full text document...
-Autosave=Autosave
A\ local\ copy\ will\ be\ opened.=A local copy will be opened.
Autosave\ local\ libraries=Autosave local libraries
Automatically\ save\ the\ library\ to=Automatically save the library to
diff --git a/src/test/java/org/jabref/gui/entryeditor/SourceTabTest.java b/src/test/java/org/jabref/gui/entryeditor/SourceTabTest.java
index b2d9f71ea0d..b57ff28e6c1 100644
--- a/src/test/java/org/jabref/gui/entryeditor/SourceTabTest.java
+++ b/src/test/java/org/jabref/gui/entryeditor/SourceTabTest.java
@@ -1,6 +1,7 @@
package org.jabref.gui.entryeditor;
import java.util.Collections;
+import java.util.List;
import javafx.scene.Scene;
import javafx.scene.control.Label;
@@ -18,6 +19,7 @@
import org.jabref.logic.importer.ImportFormatPreferences;
import org.jabref.model.database.BibDatabaseContext;
import org.jabref.model.entry.BibEntry;
+import org.jabref.model.entry.field.StandardField;
import org.jabref.model.entry.field.UnknownField;
import org.jabref.model.util.DummyFileUpdateMonitor;
import org.jabref.testutils.category.GUITest;
@@ -52,8 +54,9 @@ public void onStart(Stage stage) {
ImportFormatPreferences importFormatPreferences = mock(ImportFormatPreferences.class);
when(importFormatPreferences.getFieldContentFormatterPreferences())
.thenReturn(mock(FieldContentFormatterPreferences.class));
+ FieldWriterPreferences fieldWriterPreferences = new FieldWriterPreferences(true, List.of(StandardField.MONTH), new FieldContentFormatterPreferences());
- sourceTab = new SourceTab(new BibDatabaseContext(), new CountingUndoManager(), new FieldWriterPreferences(), importFormatPreferences, new DummyFileUpdateMonitor(), mock(DialogService.class), stateManager, keyBindingRepository);
+ sourceTab = new SourceTab(new BibDatabaseContext(), new CountingUndoManager(), fieldWriterPreferences, importFormatPreferences, new DummyFileUpdateMonitor(), mock(DialogService.class), stateManager, keyBindingRepository);
pane = new TabPane(
new Tab("main area", area),
new Tab("other tab", new Label("some text")),
diff --git a/src/test/java/org/jabref/logic/bibtex/BibEntryWriterTest.java b/src/test/java/org/jabref/logic/bibtex/BibEntryWriterTest.java
index 497b2564a34..e3c47275f8f 100644
--- a/src/test/java/org/jabref/logic/bibtex/BibEntryWriterTest.java
+++ b/src/test/java/org/jabref/logic/bibtex/BibEntryWriterTest.java
@@ -42,7 +42,7 @@
class BibEntryWriterTest {
private static ImportFormatPreferences importFormatPreferences;
- private StringWriter stringWriter = new StringWriter();
+ private final StringWriter stringWriter = new StringWriter();
private BibWriter bibWriter = new BibWriter(stringWriter, OS.NEWLINE);
private BibEntryWriter bibEntryWriter;
private final FileUpdateMonitor fileMonitor = new DummyFileUpdateMonitor();
@@ -50,7 +50,7 @@ class BibEntryWriterTest {
@BeforeEach
void setUpWriter() {
importFormatPreferences = mock(ImportFormatPreferences.class, Answers.RETURNS_DEEP_STUBS);
- FieldWriterPreferences fieldWriterPreferences = mock(FieldWriterPreferences.class, Answers.RETURNS_DEEP_STUBS);
+ FieldWriterPreferences fieldWriterPreferences = new FieldWriterPreferences(true, List.of(StandardField.MONTH), new FieldContentFormatterPreferences());
bibEntryWriter = new BibEntryWriter(new FieldWriter(fieldWriterPreferences), new BibEntryTypesManager());
}
@@ -556,6 +556,30 @@ void monthApril() throws Exception {
stringWriter.toString());
}
+ @Test
+ void filenameIsUnmodifiedDuringWrite() throws Exception {
+ // source: https://github.com/JabRef/jabref/issues/7012#issuecomment-707788107
+ String bibtexEntry = "@Book{Hue17," + OS.NEWLINE +
+ " author = {Rudolf Huebener}," + OS.NEWLINE +
+ " date = {2017}," + OS.NEWLINE +
+ " title = {Leiter, Halbleiter, Supraleiter}," + OS.NEWLINE +
+ " doi = {10.1007/978-3-662-53281-2}," + OS.NEWLINE +
+ " publisher = {Springer Berlin Heidelberg}," + OS.NEWLINE +
+ " file = {:Hue17 - Leiter # Halbleiter # Supraleiter.pdf:PDF}," + OS.NEWLINE +
+ " timestamp = {2020.10.13}," + OS.NEWLINE +
+ "}" + OS.NEWLINE;
+
+ // read in bibtex string
+ ParserResult result = new BibtexParser(importFormatPreferences, fileMonitor).parse(new StringReader(bibtexEntry));
+ Collection entries = result.getDatabase().getEntries();
+ BibEntry entry = entries.iterator().next();
+
+ // write out bibtex string
+ bibEntryWriter.write(entry, bibWriter, BibDatabaseMode.BIBTEX);
+
+ assertEquals(bibtexEntry, stringWriter.toString());
+ }
+
@Test
void addFieldWithLongerLength() throws IOException {
// @formatter:off
diff --git a/src/test/java/org/jabref/logic/bibtex/FieldWriterTests.java b/src/test/java/org/jabref/logic/bibtex/FieldWriterTests.java
index 9480c8c500b..6449aff37b3 100644
--- a/src/test/java/org/jabref/logic/bibtex/FieldWriterTests.java
+++ b/src/test/java/org/jabref/logic/bibtex/FieldWriterTests.java
@@ -1,26 +1,58 @@
package org.jabref.logic.bibtex;
-import java.util.Collections;
+import java.util.List;
+import java.util.stream.Stream;
import org.jabref.logic.util.OS;
import org.jabref.model.entry.field.StandardField;
import org.jabref.model.entry.field.UnknownField;
+import org.jabref.model.strings.StringUtil;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
-import org.mockito.Answers;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
-import static org.mockito.Mockito.mock;
class FieldWriterTests {
private FieldWriter writer;
+ public static Stream getMarkdowns() {
+ return Stream.of(Arguments.of("""
+ # Changelog
+
+ All notable changes to this project will be documented in this file.
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
+ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `#NUM`.
+ In case, there is no issue present, the pull request implementing the feature is linked.
+
+ Note that this project **does not** adhere to [Semantic Versioning](http://semver.org/).
+
+ ## [Unreleased]"""),
+ // Source: https://github.com/JabRef/jabref/issues/7010#issue-720030293
+ Arguments.of(
+ """
+ #### Goal
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit,
+ #### Achievement\s
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit,
+ #### Method
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit,
+ """
+ ),
+ // source: https://github.com/JabRef/jabref/issues/8303 --> bug2.txt
+ Arguments.of("Particularly, we equip SOVA – a Semantic and Ontological Variability Analysis method")
+ );
+ }
+
@BeforeEach
void setUp() {
- this.writer = new FieldWriter(mock(FieldWriterPreferences.class, Answers.RETURNS_DEEP_STUBS));
+ FieldWriterPreferences fieldWriterPreferences = new FieldWriterPreferences(true, List.of(StandardField.MONTH), new FieldContentFormatterPreferences());
+ writer = new FieldWriter(fieldWriterPreferences);
}
@Test
@@ -113,12 +145,11 @@ void hashEnclosedWordsGetRealStringsInMonthField() throws Exception {
assertEquals("jan #{ - } # feb", writer.write(StandardField.MONTH, text));
}
- @Test
- void hashEnclosedWordsGetRealStringsInMonthFieldBecauseMonthIsStandardField() throws Exception {
- FieldWriterPreferences fieldWriterPreferences = new FieldWriterPreferences(
- false, Collections.emptyList(), new FieldContentFormatterPreferences());
- FieldWriter formatter = new FieldWriter(fieldWriterPreferences);
- String text = "#jan# - #feb#";
- assertEquals("jan #{ - } # feb", formatter.write(StandardField.MONTH, text));
+ @ParameterizedTest
+ @MethodSource("getMarkdowns")
+ void keepHashSignInComment(String text) throws Exception {
+ String writeResult = writer.write(StandardField.COMMENT, text);
+ String resultWithLfAsNewLineSeparator = StringUtil.unifyLineBreaks(writeResult, "\n");
+ assertEquals("{" + text + "}", resultWithLfAsNewLineSeparator);
}
}
diff --git a/src/test/java/org/jabref/logic/exporter/EmbeddedBibFilePdfExporterTest.java b/src/test/java/org/jabref/logic/exporter/EmbeddedBibFilePdfExporterTest.java
index 5deca4549bd..5ec6811977a 100644
--- a/src/test/java/org/jabref/logic/exporter/EmbeddedBibFilePdfExporterTest.java
+++ b/src/test/java/org/jabref/logic/exporter/EmbeddedBibFilePdfExporterTest.java
@@ -7,6 +7,7 @@
import java.util.List;
import java.util.stream.Stream;
+import org.jabref.logic.bibtex.FieldContentFormatterPreferences;
import org.jabref.logic.bibtex.FieldWriterPreferences;
import org.jabref.logic.importer.ImportFormatPreferences;
import org.jabref.logic.importer.fileformat.PdfEmbeddedBibFileImporter;
@@ -114,7 +115,7 @@ void setUp() throws IOException {
bibDatabaseMode = BibDatabaseMode.BIBTEX;
bibEntryTypesManager = new BibEntryTypesManager();
- fieldWriterPreferences = new FieldWriterPreferences();
+ FieldWriterPreferences fieldWriterPreferences = new FieldWriterPreferences(true, List.of(StandardField.MONTH), new FieldContentFormatterPreferences());
importer = new PdfEmbeddedBibFileImporter(importFormatPreferences);
exporter = new EmbeddedBibFilePdfExporter(bibDatabaseMode, bibEntryTypesManager, fieldWriterPreferences);
diff --git a/src/test/java/org/jabref/logic/exporter/ExporterTest.java b/src/test/java/org/jabref/logic/exporter/ExporterTest.java
index 810f32800d8..34d1d5b1477 100644
--- a/src/test/java/org/jabref/logic/exporter/ExporterTest.java
+++ b/src/test/java/org/jabref/logic/exporter/ExporterTest.java
@@ -10,6 +10,7 @@
import java.util.List;
import java.util.stream.Stream;
+import org.jabref.logic.bibtex.FieldContentFormatterPreferences;
import org.jabref.logic.bibtex.FieldWriterPreferences;
import org.jabref.logic.layout.LayoutFormatterPreferences;
import org.jabref.logic.xmp.XmpPreferences;
@@ -17,6 +18,7 @@
import org.jabref.model.database.BibDatabaseMode;
import org.jabref.model.entry.BibEntry;
import org.jabref.model.entry.BibEntryTypesManager;
+import org.jabref.model.entry.field.StandardField;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.io.TempDir;
@@ -48,7 +50,7 @@ private static Stream