diff --git a/HyperKitty-1.3.8.tar.gz b/HyperKitty-1.3.8.tar.gz
deleted file mode 100644
index c578a74..0000000
--- a/HyperKitty-1.3.8.tar.gz
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:8fffccadba2cfe0d4119e9c746639ee46bc0cdae67bbf99c84081d2d0bbd87b8
-size 2556166
diff --git a/hyperkitty-1.3.9.tar.gz b/hyperkitty-1.3.9.tar.gz
new file mode 100644
index 0000000..581dffd
--- /dev/null
+++ b/hyperkitty-1.3.9.tar.gz
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:05f842878cd971fc2821fb9b5bff8c5165f0875c85387fe3a5175076c8fa94c1
+size 2204377
diff --git a/hyperkitty-1.3.9.tar.gz.asc b/hyperkitty-1.3.9.tar.gz.asc
new file mode 100644
index 0000000..294213e
--- /dev/null
+++ b/hyperkitty-1.3.9.tar.gz.asc
@@ -0,0 +1,16 @@
+-----BEGIN PGP SIGNATURE-----
+
+iQIzBAABCAAdFiEEVB6gRIRTOU/3eg7MnZsroGHQpnwFAmXdpUoACgkQnZsroGHQ
+pnyY9g//RnBU9jWIctSQSxpU5KkSigsznJ98WfrZDt8bJus/AIt9heMSKHsnOo7s
+DkU6Bd+W92bk685nUJxLws4AncsWXqGnyANI2N8BWdTCTXDBgAPSlr9cryqO7rM7
+n95eIMX8N40nS9WUeIV3qlHuDR0eBaNB0GseLu24W+JbB+JCKbxLn/nQT3MVeno4
+WbAhq8NAQsE1IFbUTVyyoaETTuHbCkNoetmpz+OPR70zKs57as78FAYaGrOPdWpL
+10DxIDOqQS4SZu9Ca1pv5avDOuP+1dkyR584mY462GX1yjb5m2IIIocBnOGbgqaL
+Mz7cuc186e9KHWk43uPecj5i02D1oyoQ2HqswNkeT/p1It0H0vO86UI79wuewes6
+WOvLibO0FnbINjv3ckLTi0JzpLSe4tVkJhzt59NeYkB0S8X9LXGM7MTXxiJYQhDP
+orVGGTd7AFtA0QLqKH75ZgI1/vlpSeAJe5+tYORByPWCfeKZCyhe6sDEgqj4E+Fc
+XDZov5gyS/b1yhvpU1OeaWKUh613PLnfSVpo8lS0mbYENAApkMNZkXGbssqXnDZP
+Gtkj6PGHVBEN1rZWhKehMjPBvGuyfu1Jt0BxS99SbMKnKuUbPgm1MCUCgBvTZ3P0
+1Ca6l2n06RJ7G+7jorPQhkPXOLJiG/73+Cj4K2uqhZe3pxwooh8=
+=Ww80
+-----END PGP SIGNATURE-----
diff --git a/mistune3.patch b/mistune3.patch
deleted file mode 100644
index 5f741b0..0000000
--- a/mistune3.patch
+++ /dev/null
@@ -1,596 +0,0 @@
-From 2d123efddf474b6cc367b16e59ba9b99e95164e1 Mon Sep 17 00:00:00 2001
-From: Abhilash Raj This is the response. This is the response. https://some.url/llasdfjaksdgfjsdfgkjasdfbgksdfjgbsdfkgjbsdflkgjbsdflgksjdhf... https://some.url/llasdfjaksdgfjsdfgkjasdfbgksdfjgbsdfkgjbsdflkgjbsdflgksjdhf... This is the replied text.{text}
')
-
-- def emphasis(self, marker, text):
-+ def emphasis(self, text, marker):
- """Emphasis with marker included."""
- return super().emphasis(marker + text + marker)
-
-- def strong(self, marker, text):
-+ def strong(self, text, marker):
- """Strong with marker included."""
- return super().strong(marker + text + marker)
-
-@@ -42,7 +44,7 @@ class MyRenderer(mistune.HTMLRenderer):
- return ''.format(
- src=src, title=title, alt=alt)
-
-- def image(self, alt, src, title):
-+ def image(self, alt, url, title=None):
- """Render image if configured to do so.
-
- HYPERKITTY_RENDER_INLINE_IMAGE configuration allows for
-@@ -50,10 +52,10 @@ class MyRenderer(mistune.HTMLRenderer):
- default since embeded images can cause problems.
- """
- if getattr(settings, 'HYPERKITTY_RENDER_INLINE_IMAGE', False):
-- return super().image(src, alt, title, )
-- return self._md_style_img(src, title, alt)
-+ return super().image(alt, url, title)
-+ return self._md_style_img(url, title, alt)
-
-- def link(self, text=None, url=None, title=None):
-+ def link(self, text, url, title=None):
- """URL link renderer that truncates the length of the URL.
-
- This only does it for the URLs that are not hyperlinks by just literal
-@@ -67,7 +69,7 @@ class MyRenderer(mistune.HTMLRenderer):
-
- s = '' + (text or url) + ''
-
-
-@@ -79,13 +81,13 @@ class InlineParser(mistune.inline_parser.InlineParser):
- ‘emphasis’ or ‘strong’ node.
- """
-
-- def tokenize_emphasis(self, m, state):
-- marker = m.group(1)
-- text = m.group(2)
-- if len(marker) == 1:
-- return 'emphasis', marker, self.render(text, state)
-- return 'strong', marker, self.render(text, state)
--
-+ def parse_emphasis(self, m, state):
-+ end_pos = super().parse_emphasis(m, state)
-+ last_token = state.tokens[-1].copy()
-+ marker = m.group(0)
-+ last_token['attrs'] = {'marker': marker}
-+ state.tokens[-1] = last_token
-+ return end_pos
-
- def remove_header_rules(rules):
- rules = list(rules)
-@@ -97,7 +99,7 @@ def remove_header_rules(rules):
-
- class BlockParser(mistune.block_parser.BlockParser):
- """A copy of Mistune's block parser with header parsing rules removed."""
-- RULE_NAMES = remove_header_rules(
-+ DEFAULT_RULES = remove_header_rules(
- mistune.block_parser.BlockParser.DEFAULT_RULES)
-
-
-diff --git a/hyperkitty/tests/test_templatetags.py b/hyperkitty/tests/test_templatetags.py
-index 79372d84..b1d83177 100644
---- a/hyperkitty/tests/test_templatetags.py
-+++ b/hyperkitty/tests/test_templatetags.py
-@@ -156,6 +156,7 @@ On Fri, 09.11.12 11:27, Someone wrote:
- > This is the first quoted line
- > On Fri 07.25.12, Aperson wrote:
- >> This is the second quoted line.
-+
- This is the response.
- """
- expected = (
-@@ -167,6 +168,8 @@ This is the response.
- ''
- '{text}
')
-@@ -62,7 +61,10 @@ class MyRenderer(mistune.HTMLRenderer):
- URLs (text=None) so text is same as URL.
- It also adds target=“_blank” so that the URLs open in a new tab.
- """
-- if text is None:
-+ # text can be none of same as url in case of autolink parsing. This
-+ # will truncate the length of the URL in both cases but preserve
-+ # the actual URL destination in the hyperlink.
-+ if text is None or text == url:
- text = url
- if len(text) > 76:
- text = url[:76] + '...'
-@@ -103,26 +105,26 @@ class BlockParser(mistune.block_parser.BlockParser):
- mistune.block_parser.BlockParser.DEFAULT_RULES)
-
-
--OUTLOOK_REPLY_PATTERN = re.compile(
-+OUTLOOK_REPLY_PATTERN = (
- r'^-------- Original message --------\n'
-- r'([\s\S]+)', # everything after newline.
-- re.M
-+ r'(?P
diff --git a/python-HyperKitty.keyring b/python-HyperKitty.keyring
new file mode 100644
index 0000000..45104e2
--- /dev/null
+++ b/python-HyperKitty.keyring
@@ -0,0 +1,90 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+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
+=s7HB
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/python-HyperKitty.spec b/python-HyperKitty.spec
index 6741a32..1632340 100644
--- a/python-HyperKitty.spec
+++ b/python-HyperKitty.spec
@@ -66,14 +66,16 @@
%define plainpython python
Name: python-HyperKitty
-Version: 1.3.8
+Version: 1.3.9
Release: 0
Summary: A web interface to access GNU Mailman v3 archives
License: GPL-3.0-only
URL: https://gitlab.com/mailman/hyperkitty
#
-Source0: https://files.pythonhosted.org/packages/source/H/HyperKitty/HyperKitty-%{version}.tar.gz
-Source1: python-HyperKitty-rpmlintrc
+Source0: https://gitlab.com/mailman/hyperkitty/-/releases/%{version}/downloads/hyperkitty-%{version}.tar.gz
+Source1: https://gitlab.com/mailman/hyperkitty/-/releases/%{version}/downloads/hyperkitty-%{version}.tar.gz.asc
+Source2: python-HyperKitty.keyring
+Source3: python-HyperKitty-rpmlintrc
#
Source10: hyperkitty-manage.sh
Source12: hyperkitty.uwsgi
@@ -87,8 +89,6 @@ Source30: README.SUSE.md
# PATCH-FIX-OPENSUSE hyperkitty-settings.patch mcepl@suse.com
# hard-code locations of configuration files
Patch0: hyperkitty-settings.patch
-# PATCH-FIX-UPSTREAM mistune3.patch gl#mailman/hyperkitty#541
-Patch2: mistune3.patch
#
# PATCH-FIX-UPSTREAM gl-mr300-add-opengraph-metadata.patch gl#mailman/hyperkitty#300
Patch98: gl-mr300-add-opengraph-metadata.patch
@@ -104,6 +104,7 @@ BuildRequires: %{python_module django-gravatar2 >= %{django_gravatar2_min_versi
BuildRequires: %{python_module isort}
BuildRequires: %{python_module mailmanclient >= %{mailmanclient_min_version}}
BuildRequires: %{python_module mistune >= %{mistune_min_version}}
+BuildRequires: %{python_module pdm}
BuildRequires: %{python_module pip}
BuildRequires: %{python_module setuptools}
BuildRequires: %{python_module wheel}
@@ -212,7 +213,7 @@ BuildRequires: sysuser-tools
System user for HyperKitty.
%prep
-%setup -n HyperKitty-%{version}
+%setup -n hyperkitty-%{version}
cp %{SOURCE30} .
touch settings_local.py
@@ -360,10 +361,10 @@ fi
%service_del_postun %{hyperkitty_services}
%files -n %{hyperkitty_pkgname}
-%doc AUTHORS.txt README.rst example_project doc/*.rst
+%doc AUTHORS.txt README.rst example_project
%license COPYING.txt
%{mypython_sitelib}/hyperkitty
-%{mypython_sitelib}/HyperKitty-%{version}*-info
+%{mypython_sitelib}/hyperkitty-%{version}*-info
%files -n %{hyperkitty_pkgname}-web
%doc README.SUSE.md