From aff3a89c3cec04eda096e8f27115e36108ee6286 Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Sun, 4 Oct 2020 18:55:33 +0300 Subject: Change guides system to content system As this system will be used for more than just guides, I had to do some refactoring to match this system with plans. Basically now there isn't guides, but articles instead. --- pydis_site/static/css/content/articles.css | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 pydis_site/static/css/content/articles.css (limited to 'pydis_site/static/css/content') diff --git a/pydis_site/static/css/content/articles.css b/pydis_site/static/css/content/articles.css new file mode 100644 index 00000000..fa7a0ba5 --- /dev/null +++ b/pydis_site/static/css/content/articles.css @@ -0,0 +1,7 @@ +.breadcrumb-section { + padding: 1rem; +} + +i.has-icon-padding { + padding: 0 10px 25px 0; +} -- cgit v1.2.3 From 3d32585d8433252cc78115a744a8117c7210f3ad Mon Sep 17 00:00:00 2001 From: kosayoda Date: Tue, 23 Mar 2021 16:00:07 +0800 Subject: Style
 tag backgrounds same as .

This makes it consistent with the django-wiki version of the code
blocks, which looks neater.
---
 pydis_site/static/css/content/articles.css | 9 +++++++++
 1 file changed, 9 insertions(+)

(limited to 'pydis_site/static/css/content')

diff --git a/pydis_site/static/css/content/articles.css b/pydis_site/static/css/content/articles.css
index fa7a0ba5..f46d6b15 100644
--- a/pydis_site/static/css/content/articles.css
+++ b/pydis_site/static/css/content/articles.css
@@ -5,3 +5,12 @@
 i.has-icon-padding {
     padding: 0 10px 25px 0;
 }
+
+pre {
+    /*
+     * Style it the same as the  tag, since highlight.js does not style
+     * backgrounds of 
 tags but bulma does, resulting in a weird off-white
+     * border.
+     */
+    background-color: #282c34;
+}
-- 
cgit v1.2.3


From 367ba267c4dbc6d406922f80bc4337ee9a0139a0 Mon Sep 17 00:00:00 2001
From: kosayoda 
Date: Tue, 23 Mar 2021 18:24:56 +0800
Subject: Rename `articles` to `pages`.

Articles was a good name, but we want an `articles` category in
the future. `/pages/guides/` and `/pages/articles/` are clearer in name
than `/articles/guides/` and `/articles/articles/`.
---
 pydis_site/apps/content/tests/test_utils.py       |  70 ++++++------
 pydis_site/apps/content/tests/test_views.py       | 127 +++++++++++-----------
 pydis_site/apps/content/urls.py                   |   4 +-
 pydis_site/apps/content/utils.py                  |  36 +++---
 pydis_site/apps/content/views/__init__.py         |   6 +-
 pydis_site/apps/content/views/article_category.py |  69 ------------
 pydis_site/apps/content/views/articles.py         |  16 ---
 pydis_site/apps/content/views/page_category.py    |  69 ++++++++++++
 pydis_site/apps/content/views/pages.py            |  16 +++
 pydis_site/apps/events/urls.py                    |   4 +-
 pydis_site/apps/events/views/__init__.py          |   4 +-
 pydis_site/apps/events/views/page.py              |   2 +-
 pydis_site/apps/home/urls.py                      |   2 +-
 pydis_site/settings.py                            |   2 +-
 pydis_site/static/css/content/articles.css        |  16 ---
 pydis_site/static/css/content/page.css            |  16 +++
 pydis_site/templates/content/article.html         |  58 ----------
 pydis_site/templates/content/listing.html         |  20 ++--
 pydis_site/templates/content/page.html            |  58 ++++++++++
 pydis_site/templates/resources/resources.html     |   2 +-
 20 files changed, 299 insertions(+), 298 deletions(-)
 delete mode 100644 pydis_site/apps/content/views/article_category.py
 delete mode 100644 pydis_site/apps/content/views/articles.py
 create mode 100644 pydis_site/apps/content/views/page_category.py
 create mode 100644 pydis_site/apps/content/views/pages.py
 delete mode 100644 pydis_site/static/css/content/articles.css
 create mode 100644 pydis_site/static/css/content/page.css
 delete mode 100644 pydis_site/templates/content/article.html
 create mode 100644 pydis_site/templates/content/page.html

(limited to 'pydis_site/static/css/content')

diff --git a/pydis_site/apps/content/tests/test_utils.py b/pydis_site/apps/content/tests/test_utils.py
index 26b2bba9..e1f1b92a 100644
--- a/pydis_site/apps/content/tests/test_utils.py
+++ b/pydis_site/apps/content/tests/test_utils.py
@@ -13,20 +13,20 @@ BASE_PATH = Path(settings.BASE_DIR, "pydis_site", "apps", "content", "tests", "t
 
 
 class TestGetCategory(TestCase):
-    @override_settings(ARTICLES_PATH=BASE_PATH)
+    @override_settings(PAGES_PATH=BASE_PATH)
     def test_get_category_successfully(self):
         """Check does this get right data from category data file."""
         result = utils.get_category(["category"])
 
         self.assertEqual(result, {"name": "My Category", "description": "My Description"})
 
-    @override_settings(ARTICLES_PATH=BASE_PATH)
+    @override_settings(PAGES_PATH=BASE_PATH)
     def test_get_category_not_exists(self):
         """Check does this raise 404 error when category don't exists."""
         with self.assertRaises(Http404):
             utils.get_category(["invalid"])
 
-    @override_settings(ARTICLES_PATH=BASE_PATH)
+    @override_settings(PAGES_PATH=BASE_PATH)
     def test_get_category_not_directory(self):
         """Check does this raise 404 error when category isn't directory."""
         with self.assertRaises(Http404):
@@ -34,7 +34,7 @@ class TestGetCategory(TestCase):
 
 
 class TestGetCategories(TestCase):
-    @override_settings(ARTICLES_PATH=BASE_PATH)
+    @override_settings(PAGES_PATH=BASE_PATH)
     @patch("pydis_site.apps.content.utils.get_category")
     def test_get_categories(self, get_category_mock):
         """Check does this return test content categories."""
@@ -47,7 +47,7 @@ class TestGetCategories(TestCase):
             result, {"category": {"name": "My Category", "description": "My Description"}}
         )
 
-    @override_settings(ARTICLES_PATH=BASE_PATH)
+    @override_settings(PAGES_PATH=BASE_PATH)
     def test_get_categories_root_path(self):
         """Check does this doesn't call joinpath when getting root categories."""
         result = utils.get_categories()
@@ -55,7 +55,7 @@ class TestGetCategories(TestCase):
             result, {"category": {"name": "My Category", "description": "My Description"}}
         )
 
-    @override_settings(ARTICLES_PATH=BASE_PATH)
+    @override_settings(PAGES_PATH=BASE_PATH)
     def test_get_categories_in_category(self):
         """Check does this call joinpath when getting subcategories."""
         result = utils.get_categories(["category"])
@@ -64,11 +64,11 @@ class TestGetCategories(TestCase):
         )
 
 
-class TestGetArticles(TestCase):
-    @override_settings(ARTICLES_PATH=BASE_PATH)
-    def test_get_all_root_articles(self):
+class TestGetPages(TestCase):
+    @override_settings(PAGES_PATH=BASE_PATH)
+    def test_get_all_root_pages(self):
         """Check does this return all root level testing content."""
-        result = utils.get_articles()
+        result = utils.get_pages()
 
         for case in ["test", "test2"]:
             with self.subTest(guide=case):
@@ -77,10 +77,10 @@ class TestGetArticles(TestCase):
                 self.assertIn(case, result)
                 self.assertEqual(md.metadata, result[case])
 
-    @override_settings(ARTICLES_PATH=BASE_PATH)
-    def test_get_all_category_articles(self):
+    @override_settings(PAGES_PATH=BASE_PATH)
+    def test_get_all_category_pages(self):
         """Check does this return all category testing content."""
-        result = utils.get_articles(["category"])
+        result = utils.get_pages(["category"])
 
         md = markdown(BASE_PATH.joinpath("category", "test3.md").read_text(), extras=["metadata"])
 
@@ -88,11 +88,11 @@ class TestGetArticles(TestCase):
         self.assertEqual(md.metadata, result["test3"])
 
 
-class TestGetArticle(TestCase):
-    @override_settings(ARTICLES_PATH=BASE_PATH)
-    def test_get_root_article_success(self):
-        """Check does this return article HTML and metadata when root article exist."""
-        result = utils.get_article(["test"])
+class TestGetPage(TestCase):
+    @override_settings(PAGES_PATH=BASE_PATH)
+    def test_get_root_page_success(self):
+        """Check does this return page HTML and metadata when root page exist."""
+        result = utils.get_page(["test"])
 
         md = markdown(
             BASE_PATH.joinpath("test.md").read_text(),
@@ -107,18 +107,18 @@ class TestGetArticle(TestCase):
             ]
         )
 
-        self.assertEqual(result, {"article": str(md), "metadata": md.metadata})
+        self.assertEqual(result, {"page": str(md), "metadata": md.metadata})
 
-    @override_settings(ARTICLES_PATH=BASE_PATH)
-    def test_get_root_article_dont_exist(self):
-        """Check does this raise Http404 when root article don't exist."""
+    @override_settings(PAGES_PATH=BASE_PATH)
+    def test_get_root_page_dont_exist(self):
+        """Check does this raise Http404 when root page don't exist."""
         with self.assertRaises(Http404):
-            utils.get_article(["invalid"])
+            utils.get_page(["invalid"])
 
-    @override_settings(ARTICLES_PATH=BASE_PATH)
-    def test_get_category_article_success(self):
-        """Check does this return article HTML and metadata when category guide exist."""
-        result = utils.get_article(["category", "test3"])
+    @override_settings(PAGES_PATH=BASE_PATH)
+    def test_get_category_page_success(self):
+        """Check does this return page HTML and metadata when category guide exist."""
+        result = utils.get_page(["category", "test3"])
 
         md = markdown(
             BASE_PATH.joinpath("category", "test3.md").read_text(),
@@ -133,16 +133,16 @@ class TestGetArticle(TestCase):
             ]
         )
 
-        self.assertEqual(result, {"article": str(md), "metadata": md.metadata})
+        self.assertEqual(result, {"page": str(md), "metadata": md.metadata})
 
-    @override_settings(ARTICLES_PATH=BASE_PATH)
-    def test_get_category_article_dont_exist(self):
-        """Check does this raise Http404 when category article don't exist."""
+    @override_settings(PAGES_PATH=BASE_PATH)
+    def test_get_category_page_dont_exist(self):
+        """Check does this raise Http404 when category page don't exist."""
         with self.assertRaises(Http404):
-            utils.get_article(["category", "invalid"])
+            utils.get_page(["category", "invalid"])
 
-    @patch("pydis_site.settings.ARTICLES_PATH", new=BASE_PATH)
-    def test_get_category_article_category_dont_exist(self):
+    @patch("pydis_site.settings.PAGES_PATH", new=BASE_PATH)
+    def test_get_category_page_category_dont_exist(self):
         """Check does this raise Http404 when category don't exist."""
         with self.assertRaises(Http404):
-            utils.get_article(["invalid", "some-guide"])
+            utils.get_page(["invalid", "some-guide"])
diff --git a/pydis_site/apps/content/tests/test_views.py b/pydis_site/apps/content/tests/test_views.py
index 55bfb8ea..5ce18afb 100644
--- a/pydis_site/apps/content/tests/test_views.py
+++ b/pydis_site/apps/content/tests/test_views.py
@@ -6,143 +6,144 @@ from django.http import Http404
 from django.test import RequestFactory, TestCase, override_settings
 from django_hosts.resolvers import reverse
 
-from pydis_site.apps.content.views import ArticleOrCategoryView
+from pydis_site.apps.content.views import PageOrCategoryView
 
 BASE_PATH = Path(settings.BASE_DIR, "pydis_site", "apps", "content", "tests", "test_content")
 
 
-class TestArticlesIndexView(TestCase):
-    @patch("pydis_site.apps.content.views.articles.get_articles")
-    @patch("pydis_site.apps.content.views.articles.get_categories")
-    def test_articles_index_return_200(self, get_categories_mock, get_articles_mock):
+class TestPagesIndexView(TestCase):
+    @patch("pydis_site.apps.content.views.pages.get_pages")
+    @patch("pydis_site.apps.content.views.pages.get_categories")
+    def test_pages_index_return_200(self, get_categories_mock, get_page_mock):
         """Check that content index return HTTP code 200."""
         get_categories_mock.return_value = {}
-        get_articles_mock.return_value = {}
+        get_page_mock.return_value = {}
 
-        url = reverse('content:articles')
+        url = reverse('content:pages')
         response = self.client.get(url)
         self.assertEqual(response.status_code, 200)
-        get_articles_mock.assert_called_once()
+        get_page_mock.assert_called_once()
         get_categories_mock.assert_called_once()
 
 
-class TestArticleOrCategoryView(TestCase):
-    @override_settings(ARTICLES_PATH=BASE_PATH)
-    @patch("pydis_site.apps.content.views.article_category.utils.get_article")
-    @patch("pydis_site.apps.content.views.article_category.utils.get_category")
-    def test_article_return_code_200(self, get_category_mock, get_article_mock):
-        get_article_mock.return_value = {"guide": "test", "metadata": {}}
+class TestPageOrCategoryView(TestCase):
+    @override_settings(PAGES_PATH=BASE_PATH)
+    @patch("pydis_site.apps.content.views.page_category.utils.get_page")
+    @patch("pydis_site.apps.content.views.page_category.utils.get_category")
+    @patch("pydis_site.apps.content.views.page_category.utils.get_github_information")
+    def test_page_return_code_200(self, get_category_mock, get_page_mock):
+        get_page_mock.return_value = {"guide": "test", "metadata": {}}
 
-        url = reverse("content:article_category", args=["test2"])
+        url = reverse("content:page_category", args=["test2"])
         response = self.client.get(url)
         self.assertEqual(response.status_code, 200)
         get_category_mock.assert_not_called()
-        get_article_mock.assert_called_once()
+        get_page_mock.assert_called_once()
 
-    @patch("pydis_site.apps.content.views.article_category.utils.get_article")
-    @patch("pydis_site.apps.content.views.article_category.utils.get_category")
-    @override_settings(ARTICLES_PATH=BASE_PATH)
-    def test_article_return_404(self, get_category_mock, get_article_mock):
-        """Check that return code is 404 when invalid article provided."""
-        get_article_mock.side_effect = Http404("Article not found.")
+    @patch("pydis_site.apps.content.views.page_category.utils.get_page")
+    @patch("pydis_site.apps.content.views.page_category.utils.get_category")
+    @override_settings(PAGES_PATH=BASE_PATH)
+    def test_page_return_404(self, get_category_mock, get_page_mock):
+        """Check that return code is 404 when invalid page provided."""
+        get_page_mock.side_effect = Http404("Page not found.")
 
-        url = reverse("content:article_category", args=["invalid-guide"])
+        url = reverse("content:page_category", args=["invalid-guide"])
         response = self.client.get(url)
         self.assertEqual(response.status_code, 404)
-        get_article_mock.assert_not_called()
+        get_page_mock.assert_not_called()
         get_category_mock.assert_not_called()
 
-    @patch("pydis_site.apps.content.views.article_category.utils.get_category")
-    @patch("pydis_site.apps.content.views.article_category.utils.get_articles")
-    @patch("pydis_site.apps.content.views.article_category.utils.get_categories")
-    @override_settings(ARTICLES_PATH=BASE_PATH)
+    @patch("pydis_site.apps.content.views.page_category.utils.get_category")
+    @patch("pydis_site.apps.content.views.page_category.utils.get_pages")
+    @patch("pydis_site.apps.content.views.page_category.utils.get_categories")
+    @override_settings(PAGES_PATH=BASE_PATH)
     def test_valid_category_code_200(
             self,
             get_categories_mock,
-            get_articles_mock,
+            get_pages_mock,
             get_category_mock
     ):
         """Check that return code is 200 when visiting valid category."""
         get_category_mock.return_value = {"name": "test", "description": "test"}
-        get_articles_mock.return_value = {}
+        get_pages_mock.return_value = {}
 
-        url = reverse("content:article_category", args=["category"])
+        url = reverse("content:page_category", args=["category"])
         response = self.client.get(url)
 
         self.assertEqual(response.status_code, 200)
-        get_articles_mock.assert_called_once()
+        get_pages_mock.assert_called_once()
         get_category_mock.assert_called_once()
         get_categories_mock.assert_called_once()
 
-    @patch("pydis_site.apps.content.views.article_category.utils.get_category")
-    @patch("pydis_site.apps.content.views.article_category.utils.get_articles")
-    @patch("pydis_site.apps.content.views.article_category.utils.get_categories")
-    @override_settings(ARTICLES_PATH=BASE_PATH)
+    @patch("pydis_site.apps.content.views.page_category.utils.get_category")
+    @patch("pydis_site.apps.content.views.page_category.utils.get_pages")
+    @patch("pydis_site.apps.content.views.page_category.utils.get_categories")
+    @override_settings(PAGES_PATH=BASE_PATH)
     def test_invalid_category_code_404(
             self,
             get_categories_mock,
-            get_articles_mock,
+            get_pages_mock,
             get_category_mock
     ):
         """Check that return code is 404 when trying to visit invalid category."""
         get_category_mock.side_effect = Http404("Category not found.")
 
-        url = reverse("content:article_category", args=["invalid-category"])
+        url = reverse("content:page_category", args=["invalid-category"])
         response = self.client.get(url)
 
         self.assertEqual(response.status_code, 404)
         get_category_mock.assert_not_called()
-        get_articles_mock.assert_not_called()
+        get_pages_mock.assert_not_called()
         get_categories_mock.assert_not_called()
 
-    @patch("pydis_site.apps.content.views.article_category.utils.get_article")
-    @patch("pydis_site.apps.content.views.article_category.utils.get_category")
-    @override_settings(ARTICLES_PATH=BASE_PATH)
-    def test_valid_category_article_code_200(
+    @patch("pydis_site.apps.content.views.page_category.utils.get_page")
+    @patch("pydis_site.apps.content.views.page_category.utils.get_category")
+    @override_settings(PAGES_PATH=BASE_PATH)
+    def test_valid_category_page_code_200(
             self,
             get_category_mock,
-            get_article_mock
+            get_page_mock
     ):
-        """Check that return code is 200 when visiting valid category article."""
-        get_article_mock.return_value = {"guide": "test", "metadata": {}}
+        """Check that return code is 200 when visiting valid category page."""
+        get_page_mock.return_value = {"guide": "test", "metadata": {}}
 
-        url = reverse("content:article_category", args=["category/test3"])
+        url = reverse("content:page_category", args=["category/test3"])
         response = self.client.get(url)
         self.assertEqual(response.status_code, 200)
-        get_article_mock.assert_called_once()
+        get_page_mock.assert_called_once()
         self.assertEqual(get_category_mock.call_count, 2)
 
-    @patch("pydis_site.apps.content.views.article_category.utils.get_article")
-    @patch("pydis_site.apps.content.views.article_category.utils.get_category")
-    @override_settings(ARTICLES_PATH=BASE_PATH)
-    def test_invalid_category_article_code_404(
+    @patch("pydis_site.apps.content.views.page_category.utils.get_page")
+    @patch("pydis_site.apps.content.views.page_category.utils.get_category")
+    @override_settings(PAGES_PATH=BASE_PATH)
+    def test_invalid_category_page_code_404(
             self,
             get_category_mock,
-            get_article_mock
+            get_page_mock
     ):
-        """Check that return code is 200 when trying to visit invalid category article."""
-        get_article_mock.side_effect = Http404("Article not found.")
+        """Check that return code is 200 when trying to visit invalid category page."""
+        get_page_mock.side_effect = Http404("Page not found.")
 
-        url = reverse("content:article_category", args=["category/invalid"])
+        url = reverse("content:page_category", args=["category/invalid"])
         response = self.client.get(url)
         self.assertEqual(response.status_code, 404)
-        get_article_mock.assert_not_called()
+        get_page_mock.assert_not_called()
         get_category_mock.assert_not_called()
 
-    @override_settings(ARTICLES_PATH=BASE_PATH)
-    def test_article_category_template_names(self):
-        """Check that this return category, article template or raise Http404."""
+    @override_settings(PAGES_PATH=BASE_PATH)
+    def test_page_category_template_names(self):
+        """Check that this return category, page template or raise Http404."""
         factory = RequestFactory()
         cases = [
             {"location": "category", "output": ["content/listing.html"]},
-            {"location": "test", "output": ["content/article.html"]},
+            {"location": "test", "output": ["content/page.html"]},
             {"location": "invalid", "output": None, "raises": Http404}
         ]
 
         for case in cases:
             with self.subTest(location=case["location"], output=case["output"]):
-                request = factory.get(f"/articles/{case['location']}")
-                instance = ArticleOrCategoryView()
+                request = factory.get(f"/pages/{case['location']}")
+                instance = PageOrCategoryView()
                 instance.request = request
                 instance.kwargs = {"location": case["location"]}
 
diff --git a/pydis_site/apps/content/urls.py b/pydis_site/apps/content/urls.py
index 49a5a2ef..1406f672 100644
--- a/pydis_site/apps/content/urls.py
+++ b/pydis_site/apps/content/urls.py
@@ -4,6 +4,6 @@ from . import views
 
 app_name = "content"
 urlpatterns = [
-    path("", views.ArticlesView.as_view(), name='articles'),
-    path("/", views.ArticleOrCategoryView.as_view(), name='article_category'),
+    path("", views.PagesView.as_view(), name='pages'),
+    path("/", views.PageOrCategoryView.as_view(), name='page_category'),
 ]
diff --git a/pydis_site/apps/content/utils.py b/pydis_site/apps/content/utils.py
index 305d26b5..db502a71 100644
--- a/pydis_site/apps/content/utils.py
+++ b/pydis_site/apps/content/utils.py
@@ -9,7 +9,7 @@ from markdown2 import markdown
 
 def get_category(path: List[str]) -> Dict[str, str]:
     """Load category information by name from _info.yml."""
-    path = settings.ARTICLES_PATH.joinpath(*path)
+    path = settings.PAGES_PATH.joinpath(*path)
     if not path.exists() or not path.is_dir():
         raise Http404("Category not found.")
 
@@ -20,10 +20,10 @@ def get_categories(path: Optional[List[str]] = None) -> Dict[str, Dict]:
     """Get all categories information."""
     categories = {}
     if path is None:
-        categories_path = settings.ARTICLES_PATH
+        categories_path = settings.PAGES_PATH
         path = []
     else:
-        categories_path = settings.ARTICLES_PATH.joinpath(*path)
+        categories_path = settings.PAGES_PATH.joinpath(*path)
 
     for name in categories_path.iterdir():
         if name.is_dir():
@@ -32,34 +32,34 @@ def get_categories(path: Optional[List[str]] = None) -> Dict[str, Dict]:
     return categories
 
 
-def get_articles(path: Optional[List[str]] = None) -> Dict[str, Dict]:
-    """Get all root or category articles."""
+def get_pages(path: Optional[List[str]] = None) -> Dict[str, Dict]:
+    """Get all root or category pages."""
     if path is None:
-        base_dir = settings.ARTICLES_PATH
+        base_dir = settings.PAGES_PATH
     else:
-        base_dir = settings.ARTICLES_PATH.joinpath(*path)
+        base_dir = settings.PAGES_PATH.joinpath(*path)
 
-    articles = {}
+    pages = {}
 
     for item in base_dir.iterdir():
         if item.is_file() and item.name.endswith(".md"):
             md = markdown(item.read_text(), extras=["metadata"])
-            articles[os.path.splitext(item.name)[0]] = md.metadata
+            pages[os.path.splitext(item.name)[0]] = md.metadata
 
-    return articles
+    return pages
 
 
-def get_article(path: List[str]) -> Dict[str, Union[str, Dict]]:
-    """Get one specific article. When category is specified, get it from there."""
-    article_path = settings.ARTICLES_PATH.joinpath(*path[:-1])
+def get_page(path: List[str]) -> Dict[str, Union[str, Dict]]:
+    """Get one specific page. When category is specified, get it from there."""
+    page_path = settings.PAGES_PATH.joinpath(*path[:-1])
 
     # We need to include extension MD
-    article_path = article_path.joinpath(f"{path[-1]}.md")
-    if not article_path.exists() or not article_path.is_file():
-        raise Http404("Article not found.")
+    page_path = page_path.joinpath(f"{path[-1]}.md")
+    if not page_path.exists() or not page_path.is_file():
+        raise Http404("Page not found.")
 
     html = markdown(
-        article_path.read_text(),
+        page_path.read_text(),
         extras=[
             "metadata",
             "fenced-code-blocks",
@@ -71,4 +71,4 @@ def get_article(path: List[str]) -> Dict[str, Union[str, Dict]]:
         ]
     )
 
-    return {"article": str(html), "metadata": html.metadata}
+    return {"page": str(html), "metadata": html.metadata}
diff --git a/pydis_site/apps/content/views/__init__.py b/pydis_site/apps/content/views/__init__.py
index f92660d6..740d98e9 100644
--- a/pydis_site/apps/content/views/__init__.py
+++ b/pydis_site/apps/content/views/__init__.py
@@ -1,4 +1,4 @@
-from .article_category import ArticleOrCategoryView
-from .articles import ArticlesView
+from .page_category import PageOrCategoryView
+from .pages import PagesView
 
-__all__ = ["ArticleOrCategoryView", "ArticlesView"]
+__all__ = ["PageOrCategoryView", "PagesView"]
diff --git a/pydis_site/apps/content/views/article_category.py b/pydis_site/apps/content/views/article_category.py
deleted file mode 100644
index 2a407b99..00000000
--- a/pydis_site/apps/content/views/article_category.py
+++ /dev/null
@@ -1,69 +0,0 @@
-import typing as t
-
-from django.conf import settings
-from django.http import Http404
-from django.views.generic import TemplateView
-
-from pydis_site.apps.content import utils
-
-
-class ArticleOrCategoryView(TemplateView):
-    """Handles article and category pages."""
-
-    def get_template_names(self) -> t.List[str]:
-        """Checks does this use article template or listing template."""
-        location = self.kwargs["location"].split("/")
-        full_location = settings.ARTICLES_PATH.joinpath(*location)
-
-        if full_location.is_dir():
-            template_name = "content/listing.html"
-        elif full_location.with_suffix(".md").is_file():
-            template_name = "content/article.html"
-        else:
-            raise Http404
-
-        return [template_name]
-
-    def get_context_data(self, **kwargs) -> t.Dict[str, t.Any]:
-        """Assign proper context variables based on what resource user requests."""
-        context = super().get_context_data(**kwargs)
-
-        location: list = self.kwargs["location"].split("/")
-        full_location = settings.ARTICLES_PATH.joinpath(*location)
-
-        if full_location.is_dir():
-            context["category_info"] = utils.get_category(location)
-            context["content"] = utils.get_articles(location)
-            context["categories"] = utils.get_categories(location)
-            # Add trailing slash here to simplify template
-            context["path"] = "/".join(location) + "/"
-            context["in_category"] = True
-        elif full_location.with_suffix(".md").is_file():
-            article_result = utils.get_article(location)
-
-            if len(location) > 1:
-                context["category_data"] = utils.get_category(location[:-1])
-                context["category_data"]["raw_name"] = location[:-1][-1]
-            else:
-                context["category_data"] = {"name": None, "raw_name": None}
-
-            context["article"] = article_result
-            context["relevant_links"] = article_result["metadata"].get("relevant_links", {})
-        else:
-            raise Http404
-
-        location.pop()
-        breadcrumb_items = []
-        while len(location):
-            breadcrumb_items.insert(
-                0,
-                {
-                    "name": utils.get_category(location)["name"],
-                    "path": "/".join(location)
-                }
-            )
-            location.pop()
-
-        context["breadcrumb_items"] = breadcrumb_items
-
-        return context
diff --git a/pydis_site/apps/content/views/articles.py b/pydis_site/apps/content/views/articles.py
deleted file mode 100644
index 999002d0..00000000
--- a/pydis_site/apps/content/views/articles.py
+++ /dev/null
@@ -1,16 +0,0 @@
-from django.views.generic import TemplateView
-
-from pydis_site.apps.content.utils import get_articles, get_categories
-
-
-class ArticlesView(TemplateView):
-    """Shows all content and categories."""
-
-    template_name = "content/listing.html"
-
-    def get_context_data(self, **kwargs) -> dict:
-        """Add articles and categories data to template context."""
-        context = super().get_context_data(**kwargs)
-        context["content"] = get_articles()
-        context["categories"] = get_categories()
-        return context
diff --git a/pydis_site/apps/content/views/page_category.py b/pydis_site/apps/content/views/page_category.py
new file mode 100644
index 00000000..f00a79ee
--- /dev/null
+++ b/pydis_site/apps/content/views/page_category.py
@@ -0,0 +1,69 @@
+import typing as t
+
+from django.conf import settings
+from django.http import Http404
+from django.views.generic import TemplateView
+
+from pydis_site.apps.content import utils
+
+
+class PageOrCategoryView(TemplateView):
+    """Handles pages and page categories."""
+
+    def get_template_names(self) -> t.List[str]:
+        """Checks does this use page template or listing template."""
+        location = self.kwargs["location"].split("/")
+        full_location = settings.PAGES_PATH.joinpath(*location)
+
+        if full_location.is_dir():
+            template_name = "content/listing.html"
+        elif full_location.with_suffix(".md").is_file():
+            template_name = "content/page.html"
+        else:
+            raise Http404
+
+        return [template_name]
+
+    def get_context_data(self, **kwargs) -> t.Dict[str, t.Any]:
+        """Assign proper context variables based on what resource user requests."""
+        context = super().get_context_data(**kwargs)
+
+        location: list = self.kwargs["location"].split("/")
+        full_location = settings.PAGES_PATH.joinpath(*location)
+
+        if full_location.is_dir():
+            context["category_info"] = utils.get_category(location)
+            context["content"] = utils.get_pages(location)
+            context["categories"] = utils.get_categories(location)
+            # Add trailing slash here to simplify template
+            context["path"] = "/".join(location) + "/"
+            context["in_category"] = True
+        elif full_location.with_suffix(".md").is_file():
+            page_result = utils.get_page(location)
+
+            if len(location) > 1:
+                context["category_data"] = utils.get_category(location[:-1])
+                context["category_data"]["raw_name"] = location[:-1][-1]
+            else:
+                context["category_data"] = {"name": None, "raw_name": None}
+
+            context["page"] = page_result
+            context["relevant_links"] = page_result["metadata"].get("relevant_links", {})
+        else:
+            raise Http404
+
+        location.pop()
+        breadcrumb_items = []
+        while len(location):
+            breadcrumb_items.insert(
+                0,
+                {
+                    "name": utils.get_category(location)["name"],
+                    "path": "/".join(location)
+                }
+            )
+            location.pop()
+
+        context["breadcrumb_items"] = breadcrumb_items
+
+        return context
diff --git a/pydis_site/apps/content/views/pages.py b/pydis_site/apps/content/views/pages.py
new file mode 100644
index 00000000..11ac0eeb
--- /dev/null
+++ b/pydis_site/apps/content/views/pages.py
@@ -0,0 +1,16 @@
+from django.views.generic import TemplateView
+
+from pydis_site.apps.content.utils import get_pages, get_categories
+
+
+class PagesView(TemplateView):
+    """Shows all pages and categories."""
+
+    template_name = "content/listing.html"
+
+    def get_context_data(self, **kwargs) -> dict:
+        """Add page and category data to template context."""
+        context = super().get_context_data(**kwargs)
+        context["content"] = get_pages()
+        context["categories"] = get_categories()
+        return context
diff --git a/pydis_site/apps/events/urls.py b/pydis_site/apps/events/urls.py
index 9a65cf1f..601451da 100644
--- a/pydis_site/apps/events/urls.py
+++ b/pydis_site/apps/events/urls.py
@@ -1,9 +1,9 @@
 from django.urls import path
 
-from pydis_site.apps.events.views import IndexView, PageView
+from pydis_site.apps.events.views import IndexView, PagesView
 
 app_name = "events"
 urlpatterns = [
     path("", IndexView.as_view(), name="index"),
-    path("/", PageView.as_view(), name="page"),
+    path("/", PagesView.as_view(), name="page"),
 ]
diff --git a/pydis_site/apps/events/views/__init__.py b/pydis_site/apps/events/views/__init__.py
index 8a107e2f..6188f723 100644
--- a/pydis_site/apps/events/views/__init__.py
+++ b/pydis_site/apps/events/views/__init__.py
@@ -1,4 +1,4 @@
 from .index import IndexView
-from .page import PageView
+from .page import PagesView
 
-__all__ = ["IndexView", "PageView"]
+__all__ = ["IndexView", "PagesView"]
diff --git a/pydis_site/apps/events/views/page.py b/pydis_site/apps/events/views/page.py
index f4c37aeb..fbedd4e8 100644
--- a/pydis_site/apps/events/views/page.py
+++ b/pydis_site/apps/events/views/page.py
@@ -5,7 +5,7 @@ from django.http import Http404
 from django.views.generic import TemplateView
 
 
-class PageView(TemplateView):
+class PagesView(TemplateView):
     """Handles event pages showing."""
 
     def get_template_names(self) -> List[str]:
diff --git a/pydis_site/apps/home/urls.py b/pydis_site/apps/home/urls.py
index bd7c0625..3c716875 100644
--- a/pydis_site/apps/home/urls.py
+++ b/pydis_site/apps/home/urls.py
@@ -8,6 +8,6 @@ urlpatterns = [
     path('', HomeView.as_view(), name='home'),
     path('admin/', admin.site.urls),
     path('resources/', include('pydis_site.apps.resources.urls')),
-    path('articles/', include('pydis_site.apps.content.urls')),
+    path('pages/', include('pydis_site.apps.content.urls')),
     path('events/', include('pydis_site.apps.events.urls', namespace='events')),
 ]
diff --git a/pydis_site/settings.py b/pydis_site/settings.py
index d509d980..0b4d9fd1 100644
--- a/pydis_site/settings.py
+++ b/pydis_site/settings.py
@@ -287,4 +287,4 @@ SITE_REPOSITORY_OWNER = "python-discord"
 SITE_REPOSITORY_NAME = "site"
 SITE_REPOSITORY_BRANCH = "master"
 
-ARTICLES_PATH = Path(BASE_DIR, "pydis_site", "apps", "content", "resources", "content")
+PAGES_PATH = Path(BASE_DIR, "pydis_site", "apps", "content", "resources", "content")
diff --git a/pydis_site/static/css/content/articles.css b/pydis_site/static/css/content/articles.css
deleted file mode 100644
index f46d6b15..00000000
--- a/pydis_site/static/css/content/articles.css
+++ /dev/null
@@ -1,16 +0,0 @@
-.breadcrumb-section {
-    padding: 1rem;
-}
-
-i.has-icon-padding {
-    padding: 0 10px 25px 0;
-}
-
-pre {
-    /*
-     * Style it the same as the  tag, since highlight.js does not style
-     * backgrounds of 
 tags but bulma does, resulting in a weird off-white
-     * border.
-     */
-    background-color: #282c34;
-}
diff --git a/pydis_site/static/css/content/page.css b/pydis_site/static/css/content/page.css
new file mode 100644
index 00000000..f46d6b15
--- /dev/null
+++ b/pydis_site/static/css/content/page.css
@@ -0,0 +1,16 @@
+.breadcrumb-section {
+    padding: 1rem;
+}
+
+i.has-icon-padding {
+    padding: 0 10px 25px 0;
+}
+
+pre {
+    /*
+     * Style it the same as the  tag, since highlight.js does not style
+     * backgrounds of 
 tags but bulma does, resulting in a weird off-white
+     * border.
+     */
+    background-color: #282c34;
+}
diff --git a/pydis_site/templates/content/article.html b/pydis_site/templates/content/article.html
deleted file mode 100644
index 69d01a8d..00000000
--- a/pydis_site/templates/content/article.html
+++ /dev/null
@@ -1,58 +0,0 @@
-{% extends 'base/base.html' %}
-{% load static %}
-
-{% block title %}{{ article.metadata.title }}{% endblock %}
-{% block head %}
-  
-  
-  
-  
-  
-  
-  
-{% endblock %}
-
-{% block content %}
-    {% include "base/navbar.html" %}
-
-    
-
-    
-
-
-

{{ article.metadata.title }}

-
-
- {{ article.article|safe }} -
-
- {% if relevant_links|length > 0 %} -
- - -
- {% endif %} -
-
-
-
-
- -{% endblock %} diff --git a/pydis_site/templates/content/listing.html b/pydis_site/templates/content/listing.html index 8c06bccc..39eae1c2 100644 --- a/pydis_site/templates/content/listing.html +++ b/pydis_site/templates/content/listing.html @@ -1,12 +1,12 @@ {% extends 'base/base.html' %} {% load static %} -{% block title %}{{ category_info.name|default:"Articles" }}{% endblock %} +{% block title %}{{ category_info.name|default:"Pages" }}{% endblock %} {% block head %} - + - + {% endblock %} {% block content %} @@ -17,12 +17,12 @@ @@ -31,7 +31,7 @@
-

{{ category_info.name|default:"Articles" }}

+

{{ category_info.name|default:"Pages" }}

{% for category, data in categories.items %}
@@ -39,18 +39,18 @@ - + {{ data.name }}

{{ data.description }}

{% endfor %} - {% for article, data in content.items %} + {% for page, data in content.items %}
- + {{ data.title }}

{{ data.short_description }}

diff --git a/pydis_site/templates/content/page.html b/pydis_site/templates/content/page.html new file mode 100644 index 00000000..3b0ebb5f --- /dev/null +++ b/pydis_site/templates/content/page.html @@ -0,0 +1,58 @@ +{% extends 'base/base.html' %} +{% load static %} + +{% block title %}{{ page.metadata.title }}{% endblock %} +{% block head %} + + + + + + + +{% endblock %} + +{% block content %} + {% include "base/navbar.html" %} + + + +
+
+
+

{{ page.metadata.title }}

+
+
+ {{ page.page|safe }} +
+
+ {% if relevant_links|length > 0 %} +
+ + +
+ {% endif %} +
+
+
+
+
+ +{% endblock %} diff --git a/pydis_site/templates/resources/resources.html b/pydis_site/templates/resources/resources.html index 2dc88a8c..491bc55e 100644 --- a/pydis_site/templates/resources/resources.html +++ b/pydis_site/templates/resources/resources.html @@ -15,7 +15,7 @@

Resources

- +

Guides

Made by us, for you

-- cgit v1.2.3 From 6ccec0d866c44cd7f9789a396ef6ec6cd2cd5df8 Mon Sep 17 00:00:00 2001 From: kosayoda Date: Wed, 24 Mar 2021 19:55:16 +0800 Subject: Replace `markdown2` with `markdown` and `python-frontmatter`. This allows us to properly escape codeblocks within markdown, permalink to headers on a page, and decouples getting metadata from a file and getting generated HTML from the Markdown content. --- Pipfile | 3 +- Pipfile.lock | 43 ++++++++++++++-- .../pydis-guides/how-to-contribute-a-page.md | 59 +++++++++++++++++++++- pydis_site/apps/content/utils.py | 32 ++++++------ pydis_site/apps/content/views/page_category.py | 15 +++--- pydis_site/static/css/content/page.css | 29 ++++++++--- pydis_site/templates/content/base.html | 2 +- pydis_site/templates/content/page.html | 4 +- 8 files changed, 146 insertions(+), 41 deletions(-) (limited to 'pydis_site/static/css/content') diff --git a/Pipfile b/Pipfile index 8af6e3ce..c2b87ab4 100644 --- a/Pipfile +++ b/Pipfile @@ -18,7 +18,8 @@ pyyaml = "~=5.1" pyuwsgi = {version = "~=2.0", sys_platform = "!='win32'"} sentry-sdk = "~=0.14" gitpython = "~=3.1.7" -markdown2 = "~=2.3.9" +markdown = "~=3.3.4" +python-frontmatter = "~=1.0" [dev-packages] coverage = "~=5.0" diff --git a/Pipfile.lock b/Pipfile.lock index 3dfb7ec6..4f8bd0d3 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "893ab5cc0b64f7bb87c0304c9fb6eb24b1856c40286fbbdb1a2bf4a0d7a6d39f" + "sha256": "a338a377b64a5d25bf925646c97d932a2d1c783fc8f40d91b6a9ab8f30c2b14e" }, "pipfile-spec": 6, "requires": { @@ -118,6 +118,14 @@ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==2.10" }, + "importlib-metadata": { + "hashes": [ + "sha256:742add720a20d0467df2f444ae41704000f50e1234f46174b51f9c6031a1bd71", + "sha256:b74159469b464a99cb8cc3e21973e4d96e05d3024d337313fedb618a6e86e6f4" + ], + "markers": "python_version < '3.8'", + "version": "==3.7.3" + }, "libsass": { "hashes": [ "sha256:1521d2a8d4b397c6ec90640a1f6b5529077035efc48ef1c2e53095544e713d1b", @@ -136,13 +144,13 @@ ], "version": "==0.20.1" }, - "markdown2": { + "markdown": { "hashes": [ - "sha256:85956d8119fa6378156fef65545d66705a842819d2e1b50379a2b9d2aaa17cf0", - "sha256:fef148e5fd68d4532286c3e2943e9d2c076a8ad781b0a70a9d599a0ffe91652d" + "sha256:31b5b491868dcc87d6c24b7e3d19a0d730d59d3e46f4eea6430a321bed387a49", + "sha256:96c3ba1261de2f7547b46a00ea8463832c921d3f9d6aba3f255a6f71386db20c" ], "index": "pypi", - "version": "==2.3.10" + "version": "==3.3.4" }, "psycopg2-binary": { "hashes": [ @@ -185,6 +193,14 @@ "index": "pypi", "version": "==2.8.6" }, + "python-frontmatter": { + "hashes": [ + "sha256:766ae75f1b301ffc5fe3494339147e0fd80bc3deff3d7590a93991978b579b08", + "sha256:e98152e977225ddafea6f01f40b4b0f1de175766322004c826ca99842d19a7cd" + ], + "index": "pypi", + "version": "==1.0.0" + }, "pytz": { "hashes": [ "sha256:83a4a90894bf38e243cf052c8b58f381bfe9a7a483f6a9cab140bc7f702ac4da", @@ -288,6 +304,15 @@ "markers": "python_version >= '3.5'", "version": "==0.4.1" }, + "typing-extensions": { + "hashes": [ + "sha256:7cb407020f00f7bfc3cb3e7881628838e69d8f3fcab2f64742a5e76b2f841918", + "sha256:99d4073b617d30288f569d3f13d2bd7548c3a7e4c8de87db09a9d29bb3a4a60c", + "sha256:dafc7639cde7f1b6e1acc0f457842a83e722ccca8eef5270af2d74792619a89f" + ], + "markers": "python_version < '3.8'", + "version": "==3.7.4.3" + }, "urllib3": { "hashes": [ "sha256:2f4da4594db7e1e110a944bb1b551fdf4e6c136ad42e4234131391e21eb5b0df", @@ -303,6 +328,14 @@ ], "index": "pypi", "version": "==5.2.0" + }, + "zipp": { + "hashes": [ + "sha256:3607921face881ba3e026887d8150cca609d517579abe052ac81fc5aeffdbd76", + "sha256:51cb66cc54621609dd593d1787f286ee42a5c0adbb4b29abea5a63edc3e03098" + ], + "markers": "python_version >= '3.6'", + "version": "==3.4.1" } }, "develop": { diff --git a/pydis_site/apps/content/resources/guides/pydis-guides/how-to-contribute-a-page.md b/pydis_site/apps/content/resources/guides/pydis-guides/how-to-contribute-a-page.md index 8967e7da..12969ba2 100644 --- a/pydis_site/apps/content/resources/guides/pydis-guides/how-to-contribute-a-page.md +++ b/pydis_site/apps/content/resources/guides/pydis-guides/how-to-contribute-a-page.md @@ -69,18 +69,75 @@ You can learn more about Markdown metadata [here](https://github.com/trentm/pyth Apart from standard Markdown, certain additions are available: +### Abbreviations +HTML `` tags can be used in markdown using this format: + +**Markdown:** +```nohighlight +This website is HTML generated from YAML and Markdown. + +*[HTML]: Hyper Text Markup Language +*[YAML]: YAML Ain't Markup Language +``` + +**Output:** + +This website is HTML +generated from YAML and Markdown. + +--- + +### Footnotes +**Markdown:** +```nohighlight +This footnote[^1] links to the bottom[^custom_label] of the page[^3]. + +[^1]: Footnote labels start with a caret `^`. +[^3]: The footnote link is numbered based on the order of the labels. +[^custom label]: Footnote labels can contain any text within square brackets. +``` + +**Output:** + +This footnote[^1] links to the bottom[^custom label] of the page[^3]. + +[^1]: Footnote labels start with a caret `^`. +[^3]: The footnote link is numbered based on the order of the labels. +[^custom label]: Footnote labels can contain any text within square brackets. + +--- + ### Tables +**Markdown:** +```nohighlight +| This is header | This is another header | +| -------------- | ---------------------- | +| An item | Another item | +``` + +**Output:** + | This is header | This is another header | | -------------- | ---------------------- | | An item | Another item | -| Big item | Small item | +--- ### Codeblock Syntax Highlighting Syntax highlighting is provided by `highlight.js`. To activate syntax highlighting, put the language directly after the starting backticks. +**Markdown:** +````nohighlight +```python +import os + +path = os.path.join("foo", "bar") +``` +```` + +**Output:** ```python import os diff --git a/pydis_site/apps/content/utils.py b/pydis_site/apps/content/utils.py index 0faf722c..11d2b792 100644 --- a/pydis_site/apps/content/utils.py +++ b/pydis_site/apps/content/utils.py @@ -1,9 +1,11 @@ from pathlib import Path -from typing import Dict, Union +from typing import Dict, Tuple +import frontmatter +import markdown import yaml from django.http import Http404 -from markdown2 import markdown +from markdown.extensions.toc import TocExtension def get_category(path: Path) -> Dict[str, str]: @@ -31,29 +33,25 @@ def get_category_pages(path: Path) -> Dict[str, Dict]: for item in path.glob("*.md"): if item.is_file(): - md = markdown(item.read_text(), extras=["metadata"]) - pages[item.stem] = md.metadata + pages[item.stem] = frontmatter.load(item) return pages -def get_page(path: Path) -> Dict[str, Union[str, Dict]]: +def get_page(path: Path) -> Tuple[str, Dict]: """Get one specific page.""" if not path.is_file(): raise Http404("Page not found.") - html = markdown( - path.read_text(encoding="utf-8"), - extras=[ - "metadata", - "fenced-code-blocks", - "highlightjs-lang", - "header-ids", - "strike", - "target-blank-links", - "tables", - "task_list" + metadata, content = frontmatter.parse(path.read_text(encoding="utf-8")) + html = markdown.markdown( + content, + extensions=[ + "extra", + # Empty string for marker to disable text searching for [TOC] + # By using a metadata key instead, we save time on long markdown documents + TocExtension(title="Table of Contents:", permalink=True, marker="") ] ) - return {"content": str(html), "metadata": html.metadata} + return str(html), metadata diff --git a/pydis_site/apps/content/views/page_category.py b/pydis_site/apps/content/views/page_category.py index 91aed7f0..4a2ed2d6 100644 --- a/pydis_site/apps/content/views/page_category.py +++ b/pydis_site/apps/content/views/page_category.py @@ -35,18 +35,19 @@ class PageOrCategoryView(TemplateView): if self.full_location.is_dir(): context["categories"] = utils.get_categories(self.full_location) + context["pages"] = utils.get_category_pages(self.full_location) + category = utils.get_category(self.full_location) - context["category_info"] = category context["page_title"] = category["name"] context["page_description"] = category["description"] - context["pages"] = utils.get_category_pages(self.full_location) + context["path"] = f"{self.location}/" # Add trailing slash here to simplify template elif self.full_location.with_suffix(".md").is_file(): - page_result = utils.get_page(self.full_location.with_suffix(".md")) - context["page"] = page_result - context["page_title"] = page_result["metadata"]["title"] - context["page_description"] = page_result["metadata"]["description"] - context["relevant_links"] = page_result["metadata"].get("relevant_links", {}) + page, metadata = utils.get_page(self.full_location.with_suffix(".md")) + context["page"] = page + context["page_title"] = metadata["title"] + context["page_description"] = metadata["description"] + context["relevant_links"] = metadata.get("relevant_links", {}) else: raise Http404 diff --git a/pydis_site/static/css/content/page.css b/pydis_site/static/css/content/page.css index f46d6b15..57d7472b 100644 --- a/pydis_site/static/css/content/page.css +++ b/pydis_site/static/css/content/page.css @@ -6,11 +6,26 @@ i.has-icon-padding { padding: 0 10px 25px 0; } -pre { - /* - * Style it the same as the tag, since highlight.js does not style - * backgrounds of
 tags but bulma does, resulting in a weird off-white
-     * border.
-     */
-    background-color: #282c34;
+/*
+ * Move padding padding from 
 tag to hljs  tags so the padding
+ * space is colored the same as the background of hljs  blocks.
+ */
+.content pre {
+    padding: 0;
+}
+
+code.hljs {
+    padding: 1.75em 2em;
+}
+
+/*
+ * Show header permalink on hover.
+ */
+.headerlink {
+    display: none;
+    padding-left: 0.5em;
+}
+
+:is(h1, h2, h3, h4, h5, h6):hover > .headerlink {
+    display: inline;
 }
diff --git a/pydis_site/templates/content/base.html b/pydis_site/templates/content/base.html
index 1508dfb3..19eec5d4 100644
--- a/pydis_site/templates/content/base.html
+++ b/pydis_site/templates/content/base.html
@@ -3,7 +3,7 @@
 
 {% block title %}{{ page_title }}{% endblock %}
 {% block head %}
-
+    
     
     
     
diff --git a/pydis_site/templates/content/page.html b/pydis_site/templates/content/page.html
index 5e820c26..06d74208 100644
--- a/pydis_site/templates/content/page.html
+++ b/pydis_site/templates/content/page.html
@@ -12,7 +12,7 @@
     {% if relevant_links|length > 0 %}
         
- {{ page.content|safe }} + {{ page|safe }}
@@ -26,6 +26,6 @@
{% else %} -
{{ page.content|safe }}
+
{{ page|safe }}
{% endif %} {% endblock %} -- cgit v1.2.3