From 37268b873ad65e6aff7b47485d20af8afa141099 Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Fri, 25 Oct 2024 17:49:53 +0200 Subject: [PATCH] Add URL regex pattern --- novelwriter/constants.py | 1 + novelwriter/text/patterns.py | 6 ++++ tests/test_text/test_text_patterns.py | 48 +++++++++++++++++++++++++-- 3 files changed, 53 insertions(+), 2 deletions(-) diff --git a/novelwriter/constants.py b/novelwriter/constants.py index 3fa2d7c8..c7c3318a 100644 --- a/novelwriter/constants.py +++ b/novelwriter/constants.py @@ -60,6 +60,7 @@ class nwConst: class nwRegEx: + URL = r"https?://(?:www\.|(?!www))[\w/()@:%_\+-.~#?&=]+" WORDS = r"\b[^\s\-\+\/–—\[\]:]+\b" BREAK = r"(?i)(? re.Pattern: + """Find URLs.""" + return self._rxUrl + @property def wordSplit(self) -> re.Pattern: """Split text into words.""" diff --git a/tests/test_text/test_text_patterns.py b/tests/test_text/test_text_patterns.py index 8877cc0c..455e1491 100644 --- a/tests/test_text/test_text_patterns.py +++ b/tests/test_text/test_text_patterns.py @@ -40,6 +40,48 @@ def allMatches(regEx: re.Pattern, text: str) -> list[list[str]]: return result +@pytest.mark.core +def testTextPatterns_Urls(): + """Test the URL regex.""" + regEx = REGEX_PATTERNS.url + + valid = [ + "http://example.com", + "http://example.com/", + "http://example.com/path+to+page", + "http://example.com/path-to-page", + "http://example.com/path_to_page", + "http://example.com/path~to~page", + "http://example.com/path/to/page", + "http://example.com/path/to/page.html", + "http://example.com/path/to/page.html#title", + "http://example.com/path/to/page.html#title%20here", + "http://example.com/path/to/page.html#title%20here", + "http://example.com/path/to/page?foo=bar&bar=baz", + "http://example.com/path/to/page.html?foo=bar&bar=baz", + "http://example.com/path/to/page.html#title?foo=bar&bar=baz", + "http://user:password@example.com/", + "http://www.example.com/", + "http://www.www.example.com/", + "http://www.www.www.example.com/", + "https://example.com", + "https://www.example.com/", + ] + invalid = [ + "hppt://example.com/", + "sftp://example.com/", + "http:/example.com/", + "http://www example com/", + "http://www\texample\tcom/", + ] + + for test in valid: + assert allMatches(regEx, f"Text {test} more text") == [[(test, 5, 5 + len(test))]] + + for test in invalid: + assert allMatches(regEx, f"Text {test} more text") == [] + + @pytest.mark.core def testTextPatterns_Words(): """Test the word split regex.""" @@ -198,8 +240,10 @@ def testTextPatterns_ShortcodesPlain(): assert allMatches(regEx, "one [x]two[/x] three") == [] - # Line Break Substitution - # ======================= + +@pytest.mark.core +def testTextPatterns_LineBreakReplace(): + """Test replacing forced line breaks.""" regEx = REGEX_PATTERNS.lineBreak assert regEx.sub("\n", "one[br]two") == "one\ntwo"