diff --git a/core/apps.py b/core/apps.py new file mode 100644 index 00000000..5ef1d600 --- /dev/null +++ b/core/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class CoreConfig(AppConfig): + name = "core" diff --git a/core/boostrenderer.py b/core/boostrenderer.py new file mode 100644 index 00000000..88ccfcf7 --- /dev/null +++ b/core/boostrenderer.py @@ -0,0 +1,43 @@ +import re + +from mistletoe import HTMLRenderer +from mistletoe.span_token import SpanToken +from pygments import highlight +from pygments.styles import get_style_by_name as get_style +from pygments.lexers import get_lexer_by_name as get_lexer, guess_lexer +from pygments.formatters.html import HtmlFormatter + + +class Youtube(SpanToken): + """ + Span token for Youtube shortcodes + Expected shortcode: `[[ youtube | U4VZ9DRdXAI ]]` + youtube is thrown out but in the shortcode for readability + """ + pattern = re.compile(r"\[\[ *(.+?) *\| *(.+?) *\]\]") + + def __init__(self, match): + self.target = match.group(2) + + +class PygmentsRenderer(HTMLRenderer): + formatter = HtmlFormatter() + formatter.noclasses = True + + def __init__(self, *extras, style='solarized-dark'): + super().__init__(*extras) + self.formatter.style = get_style(style) + + def render_block_code(self, token): + code = token.children[0].content + lexer = get_lexer(token.language) if token.language else guess_lexer(code) + return highlight(code, lexer, self.formatter) + + +class BoostRenderer(PygmentsRenderer): + def __init__(self): + super().__init__(Youtube) + + def render_youtube(self, token): + template = '' + return template.format(target=token.target) diff --git a/core/markdown.py b/core/markdown.py index d5b6eee3..09b50c2e 100644 --- a/core/markdown.py +++ b/core/markdown.py @@ -1,14 +1,15 @@ import frontmatter -from mistletoe import Document, HTMLRenderer +from core.boostrenderer import BoostRenderer +from mistletoe import Document -def process_md(): - with open("content/test.md") as f: +def process_md(filename): + with open(filename) as f: post = frontmatter.load(f) metadata = post.metadata content = post.content - with HTMLRenderer() as renderer: + with BoostRenderer() as renderer: doc = Document(content) rendered = renderer.render(doc) diff --git a/core/views.py b/core/views.py new file mode 100644 index 00000000..4beca5b4 --- /dev/null +++ b/core/views.py @@ -0,0 +1,26 @@ +import os.path + +from django.http import Http404 +from django.views.generic import TemplateView + +from .markdown import process_md + + +class MarkdownTemplateView(TemplateView): + template_name = "markdown_template.html" + + def get(self, request, *args, **kwargs): + filename = self.kwargs.get("title") + if not os.path.isfile(f"content/{filename}.md"): + raise Http404("Post not found") + + context = self.get_context_data(**kwargs) + return self.render_to_response(context) + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + filename = self.kwargs.get("title") + metadata, content = process_md(f"content/{filename}.md") + context["frontmatter"] = metadata + context["content"] = content + return context diff --git a/frontend/styles.css b/frontend/styles.css index 376fd47f..45ca6782 100644 --- a/frontend/styles.css +++ b/frontend/styles.css @@ -2,8 +2,23 @@ @tailwind components; @tailwind utilities; -/* custom classes */ - body { color: white; } + +@layer base { + h1 { + @apply text-6xl; + @apply mb-3; + } + h2 { + @apply text-4xl; + @apply my-5; + } + p { + @apply py-5; + } + pre { + @apply p-6; + } +} diff --git a/static/css/styles.css b/static/css/styles.css index 6c11ed91..7e28d744 100644 --- a/static/css/styles.css +++ b/static/css/styles.css @@ -554,6 +554,24 @@ select { outline: 1px solid ButtonText; outline: 1px auto -webkit-focus-ring-color; } + h1 { + font-size: 3.75rem; + line-height: 1; + margin-bottom: 0.75rem; +} + h2 { + font-size: 2.25rem; + line-height: 2.5rem; + margin-top: 1.25rem; + margin-bottom: 1.25rem; +} + p { + padding-top: 1.25rem; + padding-bottom: 1.25rem; +} + pre { + padding: 1.5rem; +} *, ::before, ::after { --tw-translate-x: 0; @@ -669,12 +687,6 @@ select { .left-0 { left: 0px; } -.right-0 { - right: 0px; -} -.right-4 { - right: 1rem; -} .right-3 { right: 0.75rem; } @@ -725,10 +737,6 @@ select { margin-left: 0.75rem; margin-right: 0.75rem; } -.my-11 { - margin-top: 2.75rem; - margin-bottom: 2.75rem; -} .my-6 { margin-top: 1.5rem; margin-bottom: 1.5rem; @@ -787,21 +795,18 @@ select { .mb-16 { margin-bottom: 4rem; } -.mt-11 { - margin-top: 2.75rem; -} .mb-1 { margin-bottom: 0.25rem; } -.mb-5 { - margin-bottom: 1.25rem; -} -.mr-2 { - margin-right: 0.5rem; +.mt-11 { + margin-top: 2.75rem; } .mr-1 { margin-right: 0.25rem; } +.mb-5 { + margin-bottom: 1.25rem; +} .block { display: block; } @@ -948,26 +953,16 @@ select { margin-top: calc(0.75rem * calc(1 - var(--tw-space-y-reverse))); margin-bottom: calc(0.75rem * var(--tw-space-y-reverse)); } -.space-x-11 > :not([hidden]) ~ :not([hidden]) { - --tw-space-x-reverse: 0; - margin-right: calc(2.75rem * var(--tw-space-x-reverse)); - margin-left: calc(2.75rem * calc(1 - var(--tw-space-x-reverse))); -} -.space-x-6 > :not([hidden]) ~ :not([hidden]) { - --tw-space-x-reverse: 0; - margin-right: calc(1.5rem * var(--tw-space-x-reverse)); - margin-left: calc(1.5rem * calc(1 - var(--tw-space-x-reverse))); +.space-y-11 > :not([hidden]) ~ :not([hidden]) { + --tw-space-y-reverse: 0; + margin-top: calc(2.75rem * calc(1 - var(--tw-space-y-reverse))); + margin-bottom: calc(2.75rem * var(--tw-space-y-reverse)); } .space-y-6 > :not([hidden]) ~ :not([hidden]) { --tw-space-y-reverse: 0; margin-top: calc(1.5rem * calc(1 - var(--tw-space-y-reverse))); margin-bottom: calc(1.5rem * var(--tw-space-y-reverse)); } -.space-y-11 > :not([hidden]) ~ :not([hidden]) { - --tw-space-y-reverse: 0; - margin-top: calc(2.75rem * calc(1 - var(--tw-space-y-reverse))); - margin-bottom: calc(2.75rem * var(--tw-space-y-reverse)); -} .divide-y > :not([hidden]) ~ :not([hidden]) { --tw-divide-y-reverse: 0; border-top-width: calc(1px * calc(1 - var(--tw-divide-y-reverse))); @@ -1083,9 +1078,9 @@ select { padding-top: 2.75rem; padding-bottom: 2.75rem; } -.py-16 { - padding-top: 4rem; - padding-bottom: 4rem; +.py-0 { + padding-top: 0px; + padding-bottom: 0px; } .px-5 { padding-left: 1.25rem; @@ -1111,9 +1106,9 @@ select { padding-left: 1.5rem; padding-right: 1.5rem; } -.py-0 { - padding-top: 0px; - padding-bottom: 0px; +.py-16 { + padding-top: 4rem; + padding-bottom: 4rem; } .pr-2 { padding-right: 0.5rem; @@ -1169,18 +1164,12 @@ select { .pr-11 { padding-right: 2.75rem; } -.pb-4 { - padding-bottom: 1rem; -} .text-left { text-align: left; } .text-center { text-align: center; } -.align-middle { - vertical-align: middle; -} .font-cairo { font-family: 'Cairo', sans-serif; } @@ -1266,8 +1255,6 @@ select { transition-timing-function: cubic-bezier(0.4, 0, 1, 1); } -/* custom classes */ - body { color: white; } @@ -1281,21 +1268,11 @@ body { background-color: rgb(255 159 0 / var(--tw-bg-opacity)); } -.checked\:text-orange:checked { - --tw-text-opacity: 1; - color: rgb(255 159 0 / var(--tw-text-opacity)); -} - .hover\:bg-orange:hover { --tw-bg-opacity: 1; background-color: rgb(255 159 0 / var(--tw-bg-opacity)); } -.focus\:bg-orange:focus { - --tw-bg-opacity: 1; - background-color: rgb(255 159 0 / var(--tw-bg-opacity)); -} - .focus\:text-charcoal:focus { --tw-text-opacity: 1; color: rgb(23 42 52 / var(--tw-text-opacity)); @@ -1372,47 +1349,11 @@ body { justify-content: center; } - .sm\:space-y-4 > :not([hidden]) ~ :not([hidden]) { - --tw-space-y-reverse: 0; - margin-top: calc(1rem * calc(1 - var(--tw-space-y-reverse))); - margin-bottom: calc(1rem * var(--tw-space-y-reverse)); - } - - .sm\:space-y-3 > :not([hidden]) ~ :not([hidden]) { - --tw-space-y-reverse: 0; - margin-top: calc(0.75rem * calc(1 - var(--tw-space-y-reverse))); - margin-bottom: calc(0.75rem * var(--tw-space-y-reverse)); - } - .sm\:px-6 { padding-left: 1.5rem; padding-right: 1.5rem; } - .sm\:py-4 { - padding-top: 1rem; - padding-bottom: 1rem; - } - - .sm\:py-11 { - padding-top: 2.75rem; - padding-bottom: 2.75rem; - } - - .sm\:py-6 { - padding-top: 1.5rem; - padding-bottom: 1.5rem; - } - - .sm\:px-3 { - padding-left: 0.75rem; - padding-right: 0.75rem; - } - - .sm\:pt-4 { - padding-top: 1rem; - } - .sm\:text-5xl { font-size: 3rem; line-height: 1; @@ -1440,6 +1381,11 @@ body { margin-bottom: 0px; } + .md\:my-6 { + margin-top: 1.5rem; + margin-bottom: 1.5rem; + } + .md\:mx-0 { margin-left: 0px; margin-right: 0px; @@ -1450,11 +1396,6 @@ body { margin-bottom: 2.75rem; } - .md\:my-6 { - margin-top: 1.5rem; - margin-bottom: 1.5rem; - } - .md\:mb-11 { margin-bottom: 2.75rem; } @@ -1467,20 +1408,20 @@ body { margin-top: 2rem; } - .md\:mr-11 { - margin-right: 2.75rem; + .md\:mb-0 { + margin-bottom: 0px; } - .md\:mt-0 { - margin-top: 0px; + .md\:mr-11 { + margin-right: 2.75rem; } .md\:mt-11 { margin-top: 2.75rem; } - .md\:mb-0 { - margin-bottom: 0px; + .md\:mt-0 { + margin-top: 0px; } .md\:mb-6 { @@ -1519,10 +1460,6 @@ body { width: 25%; } - .md\:w-full { - width: 100%; - } - .md\:w-1\/3 { width: 33.333333%; } @@ -1531,10 +1468,6 @@ body { width: auto; } - .md\:w-2\/3 { - width: 66.666667%; - } - .md\:max-w-7xl { max-width: 80rem; } @@ -1650,6 +1583,16 @@ body { padding-right: 2.5rem; } + .md\:py-6 { + padding-top: 1.5rem; + padding-bottom: 1.5rem; + } + + .md\:px-0 { + padding-left: 0px; + padding-right: 0px; + } + .md\:py-3 { padding-top: 0.75rem; padding-bottom: 0.75rem; @@ -1660,11 +1603,6 @@ body { padding-right: 2rem; } - .md\:px-0 { - padding-left: 0px; - padding-right: 0px; - } - .md\:py-11 { padding-top: 2.75rem; padding-bottom: 2.75rem; @@ -1675,16 +1613,6 @@ body { padding-bottom: 0px; } - .md\:py-16 { - padding-top: 4rem; - padding-bottom: 4rem; - } - - .md\:py-6 { - padding-top: 1.5rem; - padding-bottom: 1.5rem; - } - .md\:pl-6 { padding-left: 1.5rem; } diff --git a/templates/base.html b/templates/base.html index d622c6db..557d7fd6 100644 --- a/templates/base.html +++ b/templates/base.html @@ -7,6 +7,9 @@ + + + diff --git a/templates/markdown_template.html b/templates/markdown_template.html new file mode 100644 index 00000000..a09029bf --- /dev/null +++ b/templates/markdown_template.html @@ -0,0 +1,18 @@ +{% extends "base.html" %} + +{% load static %} + +{% block title %}{{ frontmatter.title }}{% endblock %} +{% block description %}{{ frontmatter.description }}{% endblock %} +{% block keywords %}{{ frontmatter.keywords }}{% endblock %} +{% block author %}{{ frontmatter.author }}{% endblock %} + +{% block content %} +
+ +
+ {{ content|safe }} +
+ +
+{% endblock %}