diff --git a/build.gradle b/build.gradle index 1a08fd86ef8..31d24b3235d 100644 --- a/build.gradle +++ b/build.gradle @@ -29,7 +29,7 @@ plugins { id 'idea' - id 'org.openrewrite.rewrite' version '6.27.0' + id 'org.openrewrite.rewrite' version '6.27.2' id "org.itsallcode.openfasttrace" version "3.0.1" } @@ -72,34 +72,34 @@ application { mainModule.set('org.jabref') applicationDefaultJvmArgs = [ - // On a change here, also adapt - // 1. "run > moduleOptions" - // 2. "deployment.yml" (macOS part) - // 3. "deployment-arm64.yml" - - // Note that the arguments are cleared for the "run" task to avoid messages like "WARNING: Unknown module: org.jabref.merged.module specified to --add-exports" - - // Fix for https://github.com/JabRef/jabref/issues/11188 - '--add-exports=javafx.base/com.sun.javafx.event=org.jabref.merged.module', - '--add-exports=javafx.controls/com.sun.javafx.scene.control=org.jabref.merged.module', - - // Fix for https://github.com/JabRef/jabref/issues/11198 - '--add-opens=javafx.graphics/javafx.scene=org.jabref.merged.module', - '--add-opens=javafx.controls/javafx.scene.control=org.jabref.merged.module', - '--add-opens=javafx.controls/com.sun.javafx.scene.control=org.jabref.merged.module', - // fix for https://github.com/JabRef/jabref/issues/11426 - '--add-opens=javafx.controls/javafx.scene.control.skin=org.jabref.merged.module', - - // Fix for https://github.com/JabRef/jabref/issues/11225 on linux - '--add-opens=javafx.controls/javafx.scene.control=org.jabref', - '--add-exports=javafx.base/com.sun.javafx.event=org.jabref', - '--add-exports=javafx.controls/com.sun.javafx.scene.control=org.jabref', - '--add-opens=javafx.graphics/javafx.scene=org.jabref', - '--add-opens=javafx.controls/javafx.scene.control=org.jabref', - '--add-opens=javafx.controls/com.sun.javafx.scene.control=org.jabref', - - '--add-opens=javafx.base/javafx.collections=org.jabref', - '--add-opens=javafx.base/javafx.collections.transformation=org.jabref' + // On a change here, also adapt + // 1. "run > moduleOptions" + // 2. "deployment.yml" (macOS part) + // 3. "deployment-arm64.yml" + + // Note that the arguments are cleared for the "run" task to avoid messages like "WARNING: Unknown module: org.jabref.merged.module specified to --add-exports" + + // Fix for https://github.com/JabRef/jabref/issues/11188 + '--add-exports=javafx.base/com.sun.javafx.event=org.jabref.merged.module', + '--add-exports=javafx.controls/com.sun.javafx.scene.control=org.jabref.merged.module', + + // Fix for https://github.com/JabRef/jabref/issues/11198 + '--add-opens=javafx.graphics/javafx.scene=org.jabref.merged.module', + '--add-opens=javafx.controls/javafx.scene.control=org.jabref.merged.module', + '--add-opens=javafx.controls/com.sun.javafx.scene.control=org.jabref.merged.module', + // fix for https://github.com/JabRef/jabref/issues/11426 + '--add-opens=javafx.controls/javafx.scene.control.skin=org.jabref.merged.module', + + // Fix for https://github.com/JabRef/jabref/issues/11225 on linux + '--add-opens=javafx.controls/javafx.scene.control=org.jabref', + '--add-exports=javafx.base/com.sun.javafx.event=org.jabref', + '--add-exports=javafx.controls/com.sun.javafx.scene.control=org.jabref', + '--add-opens=javafx.graphics/javafx.scene=org.jabref', + '--add-opens=javafx.controls/javafx.scene.control=org.jabref', + '--add-opens=javafx.controls/com.sun.javafx.scene.control=org.jabref', + + '--add-opens=javafx.base/javafx.collections=org.jabref', + '--add-opens=javafx.base/javafx.collections.transformation=org.jabref' ] } @@ -265,7 +265,7 @@ dependencies { // region HTTP clients implementation 'org.jsoup:jsoup:1.18.1' - implementation 'com.konghq:unirest-java-core:4.4.4' + implementation 'com.konghq:unirest-java-core:4.4.5' implementation 'com.konghq:unirest-modules-gson:4.4.5' implementation 'org.apache.httpcomponents.client5:httpclient5:5.4' // endregion @@ -278,7 +278,7 @@ dependencies { // route all requests to java.util.logging to SLF4J (which in turn routes to tinylog) implementation 'org.slf4j:jul-to-slf4j:2.0.16' // route all requests to log4j to SLF4J - implementation 'org.apache.logging.log4j:log4j-to-slf4j:2.24.1' + implementation 'org.apache.logging.log4j:log4j-to-slf4j:2.24.2' implementation('de.undercouch:citeproc-java:3.1.0') { exclude group: 'org.antlr' @@ -334,23 +334,23 @@ dependencies { implementation 'org.yaml:snakeyaml:2.3' // region AI - implementation 'dev.langchain4j:langchain4j:0.35.0' + implementation 'dev.langchain4j:langchain4j:0.36.0' // Even though we use jvm-openai for LLM connection, we still need this package for tokenization. - implementation('dev.langchain4j:langchain4j-open-ai:0.35.0') { + implementation('dev.langchain4j:langchain4j-open-ai:0.36.0') { exclude group: 'com.squareup.okhttp3' exclude group: 'com.squareup.retrofit2', module: 'retrofit' exclude group: 'org.jetbrains.kotlin' } - implementation('dev.langchain4j:langchain4j-mistral-ai:0.35.0') { + implementation('dev.langchain4j:langchain4j-mistral-ai:0.36.2') { exclude group: 'com.squareup.okhttp3' exclude group: 'com.squareup.retrofit2', module: 'retrofit' exclude group: 'org.jetbrains.kotlin' } - implementation('dev.langchain4j:langchain4j-google-ai-gemini:0.35.0') { + implementation('dev.langchain4j:langchain4j-google-ai-gemini:0.36.0') { exclude group: 'com.squareup.okhttp3' exclude group: 'com.squareup.retrofit2', module: 'retrofit' } - implementation('dev.langchain4j:langchain4j-hugging-face:0.35.0') { + implementation('dev.langchain4j:langchain4j-hugging-face:0.36.0') { exclude group: 'com.squareup.okhttp3' exclude group: 'com.squareup.retrofit2', module: 'retrofit' exclude group: 'org.jetbrains.kotlin' @@ -370,17 +370,17 @@ dependencies { implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8:2.0.21' // endregion - implementation 'commons-io:commons-io:2.17.0' + implementation 'commons-io:commons-io:2.18.0' // Even if "compileOnly" is used, IntelliJ always adds to module-info.java. To avoid issues during committing, we use "implementation" instead of "compileOnly" implementation 'io.github.adr:e-adr:2.0.0-SNAPSHOT' - implementation 'io.zonky.test:embedded-postgres:2.0.7' + implementation 'io.zonky.test:embedded-postgres:2.1.0' implementation enforcedPlatform('io.zonky.test.postgres:embedded-postgres-binaries-bom:17.0.0') testImplementation 'io.github.classgraph:classgraph:4.8.177' - testImplementation 'org.junit.jupiter:junit-jupiter:5.11.0' - testImplementation 'org.junit.platform:junit-platform-launcher:1.10.3' + testImplementation 'org.junit.jupiter:junit-jupiter:5.11.3' + testImplementation 'org.junit.platform:junit-platform-launcher:1.11.3' testImplementation 'org.mockito:mockito-core:5.14.2' testImplementation 'org.xmlunit:xmlunit-core:2.10.0' @@ -393,14 +393,14 @@ dependencies { testImplementation "com.github.javaparser:javaparser-symbol-solver-core:3.26.2" // recommended by https://github.com/wiremock/wiremock/issues/2149#issuecomment-1835775954 - testImplementation 'org.wiremock:wiremock-standalone:3.3.1' + testImplementation 'org.wiremock:wiremock-standalone:3.9.2' checkstyle 'com.puppycrawl.tools:checkstyle:10.20.1' // xjc needs the runtime as well for the ant task, otherwise it fails xjc group: 'org.glassfish.jaxb', name: 'jaxb-xjc', version: '3.0.2' xjc group: 'org.glassfish.jaxb', name: 'jaxb-runtime', version: '3.0.2' - rewrite(platform("org.openrewrite.recipe:rewrite-recipe-bom:2.19.0")) + rewrite(platform("org.openrewrite.recipe:rewrite-recipe-bom:2.22.0")) rewrite("org.openrewrite.recipe:rewrite-static-analysis") rewrite("org.openrewrite.recipe:rewrite-logging-frameworks") rewrite("org.openrewrite.recipe:rewrite-testing-frameworks") @@ -593,7 +593,7 @@ javadoc { version = false author = false addMultilineStringsOption("-add-exports").setValue([ - 'javafx.controls/com.sun.javafx.scene.control=org.jabref' + 'javafx.controls/com.sun.javafx.scene.control=org.jabref' ]) } } @@ -711,20 +711,20 @@ checkstyle { rewrite { activeRecipe( - 'org.jabref.config.rewrite.cleanup' + 'org.jabref.config.rewrite.cleanup' ) exclusion ( - "build.gradle", - "buildSrc/build.gradle", - "eclipse.gradle", - "settings.gradle", - "src-gen/**", - "src/main/resources/**", - "src/test/resources/**", - "**/module-info.java", - "**/*.py", - "**/*.xml", - "**/*.yml" + "build.gradle", + "buildSrc/build.gradle", + "eclipse.gradle", + "settings.gradle", + "src-gen/**", + "src/main/resources/**", + "src/test/resources/**", + "**/module-info.java", + "**/*.py", + "**/*.xml", + "**/*.yml" ) plainTextMask("**/*.md") failOnDryRunResults = true @@ -734,7 +734,7 @@ modernizer { failOnViolations = false includeTestClasses = true exclusions = [ - 'java/util/Optional.get:()Ljava/lang/Object;' + 'java/util/Optional.get:()Ljava/lang/Object;' ] } @@ -839,11 +839,11 @@ jlink { 'org.bouncycastle.pqc.jcajce.provider.BouncyCastlePQCProvider' provides 'kong.unirest.core.json.JsonEngine' with 'kong.unirest.modules.gson.GsonEngine'; provides 'ai.djl.repository.zoo.ZooProvider' with 'ai.djl.engine.rust.zoo.RsZooProvider', - 'ai.djl.huggingface.zoo.HfZooProvider', - 'ai.djl.pytorch.zoo.PtZooProvider', - 'ai.djl.repository.zoo.DefaultZooProvider'; + 'ai.djl.huggingface.zoo.HfZooProvider', + 'ai.djl.pytorch.zoo.PtZooProvider', + 'ai.djl.repository.zoo.DefaultZooProvider'; provides 'ai.djl.engine.EngineProvider' with 'ai.djl.engine.rust.RsEngineProvider', - 'ai.djl.pytorch.engine.PtEngineProvider'; + 'ai.djl.pytorch.engine.PtEngineProvider'; } jpackage { diff --git a/src/main/java/org/jabref/logic/citationkeypattern/BracketedPattern.java b/src/main/java/org/jabref/logic/citationkeypattern/BracketedPattern.java index 519fcdafd34..40c97ad3d31 100644 --- a/src/main/java/org/jabref/logic/citationkeypattern/BracketedPattern.java +++ b/src/main/java/org/jabref/logic/citationkeypattern/BracketedPattern.java @@ -1227,8 +1227,8 @@ protected static List parseFieldAndModifiers(String arg) { *
  • null if content is null
  • * */ - @VisibleForTesting - static String generateInstitutionKey(String content) { + @VisibleForTesting + static String generateInstitutionKey(String content) { if (content == null) { return null; } diff --git a/src/main/java/org/jabref/logic/citationkeypattern/CitationKeyGenerator.java b/src/main/java/org/jabref/logic/citationkeypattern/CitationKeyGenerator.java index a4eedc7ac18..e2f69f7e8a7 100644 --- a/src/main/java/org/jabref/logic/citationkeypattern/CitationKeyGenerator.java +++ b/src/main/java/org/jabref/logic/citationkeypattern/CitationKeyGenerator.java @@ -7,10 +7,14 @@ import java.util.function.Function; import java.util.regex.PatternSyntaxException; +import org.jabref.logic.formatter.bibtexfields.LatexCleanupFormatter; +import org.jabref.logic.layout.format.RemoveLatexCommandsFormatter; import org.jabref.model.FieldChange; import org.jabref.model.database.BibDatabase; import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.entry.BibEntry; +import org.jabref.model.entry.field.Field; +import org.jabref.model.entry.field.FieldFactory; import org.jabref.model.entry.types.EntryType; import org.jabref.model.strings.StringUtil; @@ -44,6 +48,7 @@ public class CitationKeyGenerator extends BracketedPattern { private final BibDatabase database; private final CitationKeyPatternPreferences citationKeyPatternPreferences; private final String unwantedCharacters; + private final RemoveLatexCommandsFormatter formatter = new RemoveLatexCommandsFormatter(); public CitationKeyGenerator(BibDatabaseContext bibDatabaseContext, CitationKeyPatternPreferences citationKeyPatternPreferences) { this(bibDatabaseContext.getMetaData().getCiteKeyPatterns(citationKeyPatternPreferences.getKeyPatterns()), @@ -91,7 +96,11 @@ public static String removeUnwantedCharacters(String key, String unwantedCharact } public static String cleanKey(String key, String unwantedCharacters) { - return removeUnwantedCharacters(key, unwantedCharacters).replaceAll("\\s", ""); + String cleanedKey = removeUnwantedCharacters(key, unwantedCharacters).replaceAll("\\s", ""); + if (cleanedKey.startsWith("-")) { + cleanedKey = cleanedKey.substring(1); + } + return cleanedKey; } /** @@ -102,10 +111,14 @@ public static String cleanKey(String key, String unwantedCharacters) { */ public String generateKey(BibEntry entry) { Objects.requireNonNull(entry); + + LatexCleanupFormatter formatter = new LatexCleanupFormatter(); +// String formattedTitle = formatter.format(entry.getField(StandardField.TITLE).orElse("")); +// entry.setField(StandardField.TITLE, formattedTitle); String currentKey = entry.getCitationKey().orElse(null); String newKey = createCitationKeyFromPattern(entry); - newKey = replaceWithRegex(newKey); + newKey = formatter.format(newKey); newKey = appendLettersToKey(newKey, currentKey); return cleanKey(newKey, unwantedCharacters); } @@ -178,7 +191,16 @@ private String createCitationKeyFromPattern(BibEntry entry) { if (citationKeyPattern == null || CitationKeyPattern.NULL_CITATION_KEY_PATTERN.equals(citationKeyPattern)) { return ""; } - return expandBrackets(citationKeyPattern.stringRepresentation(), expandBracketContent(entry)); + LatexCleanupFormatter formatter = new LatexCleanupFormatter(); + return expandBrackets(citationKeyPattern.stringRepresentation(), + fieldName -> { + // Convert fieldName (String) to Field + Field field = FieldFactory.parseField(fieldName); + + // Fetch field value and apply LaTeX cleanup + return formatter.format(entry.getField(field).orElse("")); + } + ); } /** diff --git a/src/main/java/org/jabref/logic/formatter/bibtexfields/LatexCleanupFormatter.java b/src/main/java/org/jabref/logic/formatter/bibtexfields/LatexCleanupFormatter.java index 5415156bb7b..322fe08944f 100644 --- a/src/main/java/org/jabref/logic/formatter/bibtexfields/LatexCleanupFormatter.java +++ b/src/main/java/org/jabref/logic/formatter/bibtexfields/LatexCleanupFormatter.java @@ -53,7 +53,7 @@ public String format(String oldString) { newValue = ESCAPE_PERCENT_SIGN_ONCE.matcher(newValue).replaceAll("$1\\\\%"); // escape %, but do not escapee \% again, used for comments in TeX - return newValue; + return newValue.trim(); } @Override diff --git a/src/test/java/org/jabref/logic/citationkeypattern/CitationKeyGeneratorTest.java b/src/test/java/org/jabref/logic/citationkeypattern/CitationKeyGeneratorTest.java index 913896f8c1e..61ec9bd50e7 100644 --- a/src/test/java/org/jabref/logic/citationkeypattern/CitationKeyGeneratorTest.java +++ b/src/test/java/org/jabref/logic/citationkeypattern/CitationKeyGeneratorTest.java @@ -131,6 +131,16 @@ void crossrefAndInAuthorNames() { database), DEFAULT_UNWANTED_CHARACTERS)); } + @Test + void latexCommandsAreStrippedFromCitationKey() throws ParseException { + BibEntry entry = new BibEntry() + .withCitationKey("demo24") + .withField(StandardField.TITLE, "Building \\mkbibquote{Community}"); + String pattern = "[bibtexkey] - [fulltitle]"; + String generatedKey = generateKey(entry, pattern); + assertEquals("BuildingCommunity", generatedKey); + } + @Test void andAuthorNames() throws ParseException { String bibtexString = "@ARTICLE{whatevery, author={Mari D. Herland and Mona-Iren Hauge and Ingeborg M. Helgeland}}";