diff --git a/src/main/java/org/jabref/logic/integrity/BooktitleChecker.java b/src/main/java/org/jabref/logic/integrity/BooktitleChecker.java index 3ed8b36a6e7..1353680ed48 100644 --- a/src/main/java/org/jabref/logic/integrity/BooktitleChecker.java +++ b/src/main/java/org/jabref/logic/integrity/BooktitleChecker.java @@ -2,12 +2,16 @@ import java.util.Locale; import java.util.Optional; +import java.util.regex.Pattern; import org.jabref.logic.l10n.Localization; import org.jabref.model.strings.StringUtil; public class BooktitleChecker implements ValueChecker { + private static final Pattern FULL_URL_PATTERN = Pattern.compile( + "(https?://\\S+/\\S+|www\\.\\S+/\\S+)", Pattern.CASE_INSENSITIVE); + @Override public Optional checkValue(String value) { if (StringUtil.isBlank(value)) { @@ -18,6 +22,10 @@ public Optional checkValue(String value) { return Optional.of(Localization.lang("booktitle ends with 'conference on'")); } + if (FULL_URL_PATTERN.matcher(value).find()) { + return Optional.of(Localization.lang("The book title contains a URL")); + } + return Optional.empty(); } } diff --git a/src/main/java/org/jabref/logic/integrity/TitleChecker.java b/src/main/java/org/jabref/logic/integrity/TitleChecker.java index 824c8673f46..b9fc9f459f4 100644 --- a/src/main/java/org/jabref/logic/integrity/TitleChecker.java +++ b/src/main/java/org/jabref/logic/integrity/TitleChecker.java @@ -13,6 +13,8 @@ public class TitleChecker implements ValueChecker { private static final Pattern INSIDE_CURLY_BRAKETS = Pattern.compile("\\{[^}\\{]*\\}"); private static final Pattern DELIMITERS = Pattern.compile("\\.|\\!|\\?|\\;|\\:|\\["); private static final Predicate HAS_CAPITAL_LETTERS = Pattern.compile("[\\p{Lu}\\p{Lt}]").asPredicate(); + private static final Pattern FULL_URL_PATTERN = Pattern.compile( + "(https?://\\S+/\\S+|www\\.\\S+/\\S+)", Pattern.CASE_INSENSITIVE); private final BibDatabaseContext databaseContext; @@ -40,6 +42,10 @@ public Optional checkValue(String value) { return Optional.empty(); } + if (FULL_URL_PATTERN.matcher(value).find()) { + return Optional.of(Localization.lang("The title contains a URL")); + } + String valueOnlySpacesWithinCurlyBraces = INSIDE_CURLY_BRAKETS.matcher(value).replaceAll(""); String[] splitTitle = DELIMITERS.split(valueOnlySpacesWithinCurlyBraces); diff --git a/src/main/resources/l10n/JabRef_en.properties b/src/main/resources/l10n/JabRef_en.properties index c41f97a712a..869433ff4af 100644 --- a/src/main/resources/l10n/JabRef_en.properties +++ b/src/main/resources/l10n/JabRef_en.properties @@ -2830,3 +2830,6 @@ Include=Include Exclude=Exclude Include\ or\ exclude\ cross-referenced\ entries=Include or exclude cross-referenced entries Would\ you\ like\ to\ include\ cross-reference\ entries\ in\ the\ current\ operation?=Would you like to include cross-reference entries in the current operation? + +The\ title\ contains\ a\ URL=The title contains a URL +The\ book\ title\ contains\ a\ URL=The book title contains a URL diff --git a/src/test/java/org/jabref/logic/integrity/BooktitleCheckerTest.java b/src/test/java/org/jabref/logic/integrity/BooktitleCheckerTest.java index 129b424225a..d126c21d575 100644 --- a/src/test/java/org/jabref/logic/integrity/BooktitleCheckerTest.java +++ b/src/test/java/org/jabref/logic/integrity/BooktitleCheckerTest.java @@ -25,4 +25,10 @@ void booktitleDoesNotAcceptsIfItEndsWithConferenceOn() { void booktitleIsBlank() { assertEquals(Optional.empty(), checker.checkValue(" ")); } + + @Test + void booktitleDoesNotAcceptFullURL() { + assertNotEquals(Optional.empty(), checker.checkValue("Proceedings of the https://example.com/conference")); + assertNotEquals(Optional.empty(), checker.checkValue("Workshop on www.example.com/session")); + } } diff --git a/src/test/java/org/jabref/logic/integrity/TitleCheckerTest.java b/src/test/java/org/jabref/logic/integrity/TitleCheckerTest.java index 231507a133c..6980dba7dd5 100644 --- a/src/test/java/org/jabref/logic/integrity/TitleCheckerTest.java +++ b/src/test/java/org/jabref/logic/integrity/TitleCheckerTest.java @@ -69,6 +69,20 @@ static Stream invalidTitle() { Arguments.of("bibTexDoesNotAcceptsLeadingTranslatedTitleWithOriginal ", "[This is translated title] This is a title") ); } + + @ParameterizedTest(name = "{index}. Title: \"{1}\" {0}") + @MethodSource("invalidTitlesWithURLs") + void titleShouldRaiseWarningForFullURLs(String message, String title) { + assertNotEquals(Optional.empty(), checker.checkValue(title)); + } + + static Stream invalidTitlesWithURLs() { + return Stream.of( + Arguments.of("Title contains full URL with https", "Check this out: https://example.com/something"), + Arguments.of("Title contains full URL with http", "Visit http://example.com/path"), + Arguments.of("Title contains full URL without protocol", "Found at www.example.com/something") + ); + } } @Nested