From efe784fe8a6c23248c6698aefab8bf54c5c85900 Mon Sep 17 00:00:00 2001 From: Hassan Abouelela Date: Tue, 23 Aug 2022 12:54:16 +0400 Subject: Support Hyperlinked Tag Group Replacement Signed-off-by: Hassan Abouelela --- pydis_site/apps/content/tests/test_views.py | 28 ++++++++++++++++++++++++++++ pydis_site/apps/content/utils.py | 4 ++-- pydis_site/apps/content/views/tags.py | 26 +++++++++++++++++++++++--- 3 files changed, 53 insertions(+), 5 deletions(-) (limited to 'pydis_site/apps') diff --git a/pydis_site/apps/content/tests/test_views.py b/pydis_site/apps/content/tests/test_views.py index 658ac2cc..da06fc80 100644 --- a/pydis_site/apps/content/tests/test_views.py +++ b/pydis_site/apps/content/tests/test_views.py @@ -358,6 +358,34 @@ class TagViewTests(django.test.TestCase): response.context.get("page") ) + def test_hyperlinked_group(self): + """Test hyperlinking with a group works as intended.""" + Tag.objects.create( + name="example", body="!tags group-name grouped-tag", last_commit=self.commit + ) + Tag.objects.create(name="grouped-tag", group="group-name") + + other_url = reverse("content:tag", kwargs={"location": "group-name/grouped-tag"}) + response = self.client.get("/pages/tags/example/") + self.assertEqual( + markdown.markdown(f"[!tags group-name grouped-tag]({other_url})"), + response.context.get("page") + ) + + def test_hyperlinked_extra_text(self): + """Test hyperlinking when a tag is followed by extra, unrelated text.""" + Tag.objects.create( + name="example", body="!tags other unrelated text", last_commit=self.commit + ) + Tag.objects.create(name="other") + + other_url = reverse("content:tag", kwargs={"location": "other"}) + response = self.client.get("/pages/tags/example/") + self.assertEqual( + markdown.markdown(f"[!tags other]({other_url}) unrelated text"), + response.context.get("page") + ) + def test_tag_root_page(self): """Test the root tag page which lists all tags.""" Tag.objects.create(name="tag-1", last_commit=self.commit) diff --git a/pydis_site/apps/content/utils.py b/pydis_site/apps/content/utils.py index 63f1c41c..32d3d638 100644 --- a/pydis_site/apps/content/utils.py +++ b/pydis_site/apps/content/utils.py @@ -221,7 +221,7 @@ def get_tags() -> list[Tag]: return Tag.objects.all() -def get_tag(path: str) -> typing.Union[Tag, list[Tag]]: +def get_tag(path: str, *, skip_sync: bool = False) -> typing.Union[Tag, list[Tag]]: """ Return a tag based on the search location. @@ -243,7 +243,7 @@ def get_tag(path: str) -> typing.Union[Tag, list[Tag]]: matches = [] for tag in get_tags(): if tag.name == name and tag.group == group: - if tag.last_commit is None: + if tag.last_commit is None and not skip_sync: set_tag_commit(tag) return tag elif tag.group == name and group is None: diff --git a/pydis_site/apps/content/views/tags.py b/pydis_site/apps/content/views/tags.py index a8df65db..4f4bb5a2 100644 --- a/pydis_site/apps/content/views/tags.py +++ b/pydis_site/apps/content/views/tags.py @@ -11,7 +11,12 @@ from django.views.generic import TemplateView from pydis_site.apps.content import utils from pydis_site.apps.content.models import Tag -COMMAND_REGEX = re.compile(r"`*!tags? (?P[\w\d-]+)`*") +# The following regex tries to parse a tag command +# It'll read up to two words seperated by spaces +# If the command does not include a group, the tag name will be in the `first` group +# If there's a second word after the command, or if there's a tag group, extra logic +# is necessary to determine whether it's a tag with a group, or a tag with text after it +COMMAND_REGEX = re.compile(r"`*!tags? (?P[\w-]+)(?P [\w-]+)?`*") class TagView(TemplateView): @@ -75,8 +80,23 @@ class TagView(TemplateView): # Check for tags which can be hyperlinked def sub(match: re.Match) -> str: - link = reverse("content:tag", kwargs={"location": match.group("name")}) - return f"[{match.group()}]({link})" + first, second = match.groups() + location = first + text, extra = match.group(), "" + + if second is not None: + # Possibly a tag group + try: + new_location = f"{first}/{second.strip()}" + utils.get_tag(new_location, skip_sync=True) + location = new_location + except Tag.DoesNotExist: + # Not a group, remove the second argument from the link + extra = text[text.find(second):] + text = text[:text.find(second)] + + link = reverse("content:tag", kwargs={"location": location}) + return f"[{text}]({link}){extra}" content = COMMAND_REGEX.sub(sub, content) # Add support for some embed elements -- cgit v1.2.3