diff options
| author | 2023-05-14 23:54:51 +0530 | |
|---|---|---|
| committer | 2023-05-14 23:54:51 +0530 | |
| commit | a241a397f966a4265935dfd5c92a84fdf95c52c8 (patch) | |
| tree | 83f6eb572e26e64e6ca18642013abf60f1b23d8b /pydis_site/apps/content/views | |
| parent | Update pydis_site/apps/content/resources/guides/python-guides/subclassing_bot.md (diff) | |
| parent | Merge pull request #972 from python-discord/fix-psycopg3-compatibility-in-met... (diff) | |
Merge branch 'main' into subclassing_bot
Diffstat (limited to 'pydis_site/apps/content/views')
| -rw-r--r-- | pydis_site/apps/content/views/__init__.py | 3 | ||||
| -rw-r--r-- | pydis_site/apps/content/views/page_category.py | 18 | ||||
| -rw-r--r-- | pydis_site/apps/content/views/tags.py | 123 | 
3 files changed, 135 insertions, 9 deletions
diff --git a/pydis_site/apps/content/views/__init__.py b/pydis_site/apps/content/views/__init__.py index 70ea1c7a..a969b1dc 100644 --- a/pydis_site/apps/content/views/__init__.py +++ b/pydis_site/apps/content/views/__init__.py @@ -1,3 +1,4 @@  from .page_category import PageOrCategoryView +from .tags import TagView -__all__ = ["PageOrCategoryView"] +__all__ = ["PageOrCategoryView", "TagView"] diff --git a/pydis_site/apps/content/views/page_category.py b/pydis_site/apps/content/views/page_category.py index 5af77aff..062c2bc1 100644 --- a/pydis_site/apps/content/views/page_category.py +++ b/pydis_site/apps/content/views/page_category.py @@ -1,18 +1,17 @@ -import typing as t  from pathlib import Path  import frontmatter  from django.conf import settings -from django.http import Http404 +from django.http import Http404, HttpRequest, HttpResponse  from django.views.generic import TemplateView -from pydis_site.apps.content import utils +from pydis_site.apps.content import models, utils  class PageOrCategoryView(TemplateView):      """Handles pages and page categories.""" -    def dispatch(self, request: t.Any, *args, **kwargs) -> t.Any: +    def dispatch(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:          """Conform URL path location to the filesystem path."""          self.location = Path(kwargs.get("location", "")) @@ -25,7 +24,7 @@ class PageOrCategoryView(TemplateView):          return super().dispatch(request, *args, **kwargs) -    def get_template_names(self) -> t.List[str]: +    def get_template_names(self) -> list[str]:          """Checks if the view uses the page template or listing template."""          if self.page_path.is_file():              template_name = "content/page.html" @@ -36,7 +35,7 @@ class PageOrCategoryView(TemplateView):          return [template_name] -    def get_context_data(self, **kwargs) -> t.Dict[str, t.Any]: +    def get_context_data(self, **kwargs) -> dict[str, any]:          """Assign proper context variables based on what resource user requests."""          context = super().get_context_data(**kwargs) @@ -73,7 +72,7 @@ class PageOrCategoryView(TemplateView):          return context      @staticmethod -    def _get_page_context(path: Path) -> t.Dict[str, t.Any]: +    def _get_page_context(path: Path) -> dict[str, any]:          page, metadata = utils.get_page(path)          return {              "page": page, @@ -84,7 +83,7 @@ class PageOrCategoryView(TemplateView):          }      @staticmethod -    def _get_category_context(path: Path) -> t.Dict[str, t.Any]: +    def _get_category_context(path: Path) -> dict[str, any]:          category = utils.get_category(path)          return {              "categories": utils.get_categories(path), @@ -92,4 +91,7 @@ class PageOrCategoryView(TemplateView):              "page_title": category["title"],              "page_description": category["description"],              "icon": category.get("icon"), +            "app_name": "content:page_category", +            "is_tag_listing": "/resources/tags" in path.as_posix(), +            "tag_url": models.Tag.URL_BASE,          } diff --git a/pydis_site/apps/content/views/tags.py b/pydis_site/apps/content/views/tags.py new file mode 100644 index 00000000..8d3e3321 --- /dev/null +++ b/pydis_site/apps/content/views/tags.py @@ -0,0 +1,123 @@ +import re + +import frontmatter +import markdown +from django.conf import settings +from django.http import Http404 +from django.urls import reverse +from django.views.generic import TemplateView + +from pydis_site.apps.content import utils +from pydis_site.apps.content.models import Tag + +# 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<first>[\w-]+)(?P<second> [\w-]+)?`*") + + +class TagView(TemplateView): +    """Handles tag pages.""" + +    tag: Tag | list[Tag] +    is_group: bool + +    def setup(self, *args, **kwargs) -> None: +        """Look for a tag, and configure the view.""" +        super().setup(*args, **kwargs) + +        try: +            self.tag = utils.get_tag(kwargs.get("location")) +            self.is_group = isinstance(self.tag, list) +        except Tag.DoesNotExist: +            raise Http404 + +    def get_template_names(self) -> list[str]: +        """Either return the tag page template, or the listing.""" +        if self.is_group: +            template_name = "content/listing.html" +        else: +            template_name = "content/tag.html" + +        return [template_name] + +    def get_context_data(self, **kwargs) -> dict: +        """Get the relevant context for this tag page or group.""" +        context = super().get_context_data(**kwargs) +        context["breadcrumb_items"] = [{ +            "name": utils.get_category(settings.CONTENT_PAGES_PATH / location)["title"], +            "path": location, +        } for location in (".", "tags")] + +        if self.is_group: +            self._set_group_context(context, self.tag) +        else: +            self._set_tag_context(context, self.tag) + +        return context + +    @staticmethod +    def _set_tag_context(context: dict[str, any], tag: Tag) -> None: +        """Update the context with the information for a tag page.""" +        context.update({ +            "page_title": tag.name, +            "tag": tag, +        }) + +        if tag.group: +            # Add group names to the breadcrumbs +            context["breadcrumb_items"].append({ +                "name": tag.group, +                "path": f"tags/{tag.group}", +            }) + +        # Clean up tag body +        body = frontmatter.parse(tag.body) +        content = body[1] + +        # Check for tags which can be hyperlinked +        def sub(match: re.Match) -> str: +            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 +        if embed := body[0].get("embed"): +            context["page_title"] = embed["title"] +            if image := embed.get("image"): +                content = f"![{embed['title']}]({image['url']})\n\n" + content + +        # Insert the content +        context["page"] = markdown.markdown(content, extensions=["pymdownx.superfences"]) + +    @staticmethod +    def _set_group_context(context: dict[str, any], tags: list[Tag]) -> None: +        """Update the context with the information for a group of tags.""" +        group = tags[0].group +        context.update({ +            "categories": {}, +            "pages": utils.get_tag_category(tags, collapse_groups=False), +            "page_title": group, +            "icon": "fab fa-tags", +            "is_tag_listing": True, +            "app_name": "content:tag", +            "path": f"{group}/", +            "tag_url": f"{tags[0].URL_BASE}/{group}" +        })  |