Compare commits
11 Commits
renovate/d
...
master
Author | SHA1 | Date | |
---|---|---|---|
df84b28114 | |||
a25e83a0df | |||
46669c9b17 | |||
41a04af8dc | |||
d242f94024 | |||
1421d19fdc | |||
ef7dd5f860 | |||
872fd4fc82 | |||
fffd41dc82 | |||
df3dff0708 | |||
af379243ad |
|
@ -13,7 +13,6 @@ services:
|
||||||
tmpfs:
|
tmpfs:
|
||||||
- /tmp
|
- /tmp
|
||||||
depends_on:
|
depends_on:
|
||||||
- redis
|
|
||||||
- db
|
- db
|
||||||
ports:
|
ports:
|
||||||
- 127.0.0.1:8000:8000
|
- 127.0.0.1:8000:8000
|
||||||
|
|
|
@ -1,16 +1,11 @@
|
||||||
{
|
{
|
||||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||||
"extends": [
|
"extends": [
|
||||||
"config:base"
|
"config:base",
|
||||||
|
"replacements:all",
|
||||||
|
"workarounds:all"
|
||||||
],
|
],
|
||||||
"prConcurrentLimit": 0,
|
"prConcurrentLimit": 0,
|
||||||
"packageRules": [
|
|
||||||
{
|
|
||||||
"matchUpdateTypes": ["patch"],
|
|
||||||
"schedule": ["every weekend"],
|
|
||||||
"enabled": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"regexManagers": [
|
"regexManagers": [
|
||||||
{
|
{
|
||||||
"fileMatch": ["^Dockerfile$"],
|
"fileMatch": ["^Dockerfile$"],
|
||||||
|
@ -18,5 +13,6 @@
|
||||||
"depNameTemplate": "just-containers/s6-overlay",
|
"depNameTemplate": "just-containers/s6-overlay",
|
||||||
"datasourceTemplate": "github-releases"
|
"datasourceTemplate": "github-releases"
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"dependencyDashboardApproval": true
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ Django==5.0.4
|
||||||
wagtail==5.2.5
|
wagtail==5.2.5
|
||||||
django-environ==0.11.2
|
django-environ==0.11.2
|
||||||
whitenoise[brotli]==6.6.0
|
whitenoise[brotli]==6.6.0
|
||||||
Pygments==2.17.2
|
Pygments==2.18.0
|
||||||
beautifulsoup4
|
beautifulsoup4
|
||||||
lxml==5.2.1
|
lxml==5.2.1
|
||||||
requests
|
requests
|
||||||
|
@ -29,7 +29,8 @@ django-proxy==1.2.2
|
||||||
wagtail-lite-youtube-embed==0.1.0
|
wagtail-lite-youtube-embed==0.1.0
|
||||||
django-minify-html==1.7.1
|
django-minify-html==1.7.1
|
||||||
metadata-parser==0.12.1
|
metadata-parser==0.12.1
|
||||||
django-tasks==0.1.1
|
django-tasks==0.2.0
|
||||||
|
lightningcss==0.2.0
|
||||||
|
|
||||||
# DRF OpenAPI dependencies
|
# DRF OpenAPI dependencies
|
||||||
uritemplate
|
uritemplate
|
||||||
|
|
|
@ -1,35 +0,0 @@
|
||||||
#commento {
|
|
||||||
.commento-profile-button {
|
|
||||||
@include dark-mode {
|
|
||||||
fill: $dark-mode-text;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.commento-name,
|
|
||||||
#commento-mod-tools-lock-button,
|
|
||||||
.commento-login-text,
|
|
||||||
.commento-anonymous-checkbox-container label {
|
|
||||||
@include dark-mode {
|
|
||||||
color: $dark-mode-text;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#commento-textarea-root,
|
|
||||||
#commento-guest-details-input-root,
|
|
||||||
.commento-textarea-container textarea {
|
|
||||||
@include dark-mode {
|
|
||||||
background-color: $black;
|
|
||||||
color: $dark-mode-text;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.commento-card {
|
|
||||||
@include dark-mode {
|
|
||||||
border-top: 1px solid color.adjust($black, $alpha: -0.4);
|
|
||||||
|
|
||||||
p {
|
|
||||||
color: $dark-mode-text;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
46
static/src/scss/_comments.scss
Normal file
46
static/src/scss/_comments.scss
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
#comments {
|
||||||
|
margin-top: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.comentario-text-muted,
|
||||||
|
.comentario-root,
|
||||||
|
.comentario-card .comentario-name {
|
||||||
|
@include dark-mode {
|
||||||
|
color: $dark-mode-text !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.comentario-add-comment-host,
|
||||||
|
.comentario-comment-editor textarea,
|
||||||
|
.comentario-toolbar.comentario-disabled {
|
||||||
|
background-color: transparent !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.comentario-add-comment-host:not(.comentario-editor-inserted) {
|
||||||
|
border: 1px solid color.adjust($white, $alpha: -0.5) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.comentario-comment-editor textarea {
|
||||||
|
background-color: transparent !important;
|
||||||
|
@include dark-mode {
|
||||||
|
color: $dark-mode-text !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.comentario-footer a {
|
||||||
|
color: $link !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.comentario-btn-link {
|
||||||
|
color: $link !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.comentario-card {
|
||||||
|
@include dark-mode {
|
||||||
|
border-top: 1px solid color.adjust($white, $alpha: -0.5);
|
||||||
|
|
||||||
|
p {
|
||||||
|
color: $dark-mode-text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,8 +15,8 @@ section#similar-content {
|
||||||
}
|
}
|
||||||
|
|
||||||
.media {
|
.media {
|
||||||
@include desktop {
|
transform: scale(85%);
|
||||||
transform: scale(85%);
|
margin-top: 0;
|
||||||
}
|
padding-top: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
@import "spotify";
|
@import "spotify";
|
||||||
@import "404";
|
@import "404";
|
||||||
@import "password_required";
|
@import "password_required";
|
||||||
@import "commento";
|
@import "comments";
|
||||||
@import "similar_content";
|
@import "similar_content";
|
||||||
@import "support_pill";
|
@import "support_pill";
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ from django.db.models.functions import Cast, Coalesce
|
||||||
from django.http import HttpRequest, HttpResponse, HttpResponsePermanentRedirect
|
from django.http import HttpRequest, HttpResponse, HttpResponsePermanentRedirect
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.utils.functional import cached_property
|
from django.utils.functional import cached_property
|
||||||
from metadata_parser import MetadataParser
|
from metadata_parser import ParsedResult
|
||||||
from modelcluster.fields import ParentalManyToManyField
|
from modelcluster.fields import ParentalManyToManyField
|
||||||
from wagtail.admin.panels import FieldPanel
|
from wagtail.admin.panels import FieldPanel
|
||||||
from wagtail.models import Page, PageQuerySet, Site
|
from wagtail.models import Page, PageQuerySet, Site
|
||||||
|
@ -239,7 +239,7 @@ class ExternalBlogPostPage(BaseContentPage):
|
||||||
return tags
|
return tags
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def metadata(self) -> MetadataParser:
|
def metadata(self) -> ParsedResult:
|
||||||
return get_page_metadata(self.external_url)
|
return get_page_metadata(self.external_url)
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
|
|
|
@ -2,6 +2,16 @@
|
||||||
|
|
||||||
{% load wagtail_cache navbar_tags %}
|
{% load wagtail_cache navbar_tags %}
|
||||||
|
|
||||||
|
{% block post_toc %}
|
||||||
|
<hr class="dropdown-divider" />
|
||||||
|
<li>
|
||||||
|
<a href="#similar-content">Similar content</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="#comments">Comments</a>
|
||||||
|
</li>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
{% block post_content %}
|
{% block post_content %}
|
||||||
{% if not request.is_preview %}
|
{% if not request.is_preview %}
|
||||||
{% include "common/shareon.html" %}
|
{% include "common/shareon.html" %}
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import pickle
|
||||||
|
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
|
||||||
|
@ -96,7 +98,9 @@ class ExternalBlogPostPageTestCase(TestCase):
|
||||||
def setUpTestData(cls) -> None:
|
def setUpTestData(cls) -> None:
|
||||||
cls.home_page = HomePage.objects.get()
|
cls.home_page = HomePage.objects.get()
|
||||||
cls.blog_post_list_page = BlogPostListPageFactory(parent=cls.home_page)
|
cls.blog_post_list_page = BlogPostListPageFactory(parent=cls.home_page)
|
||||||
cls.page = ExternalBlogPostPageFactory(parent=cls.blog_post_list_page)
|
cls.page = ExternalBlogPostPageFactory(
|
||||||
|
parent=cls.blog_post_list_page, external_url="https://example.com"
|
||||||
|
)
|
||||||
|
|
||||||
def test_redirects(self) -> None:
|
def test_redirects(self) -> None:
|
||||||
with self.assertNumQueries(10):
|
with self.assertNumQueries(10):
|
||||||
|
@ -107,3 +111,11 @@ class ExternalBlogPostPageTestCase(TestCase):
|
||||||
status_code=301,
|
status_code=301,
|
||||||
fetch_redirect_response=False,
|
fetch_redirect_response=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_metadata(self) -> None:
|
||||||
|
metadata = self.page.metadata
|
||||||
|
|
||||||
|
self.assertIsNone(metadata.soup)
|
||||||
|
|
||||||
|
# Confirm it can pickle
|
||||||
|
pickle.dumps(metadata)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<section class="container" id="comments">
|
<section class="container" id="comments">
|
||||||
<div id="commento"></div>
|
<comentario-comments></comentario-comments>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<script async defer src="https://commento.theorangeone.net/js/commento.js"></script>
|
<script async defer src="https://comentario.theorangeone.net/comentario.js"></script>
|
||||||
|
|
|
@ -10,6 +10,13 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block post_toc %}
|
||||||
|
<hr class="dropdown-divider" />
|
||||||
|
<li>
|
||||||
|
<a href="#comments">Comments</a>
|
||||||
|
</li>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
{% block post_content %}
|
{% block post_content %}
|
||||||
{% if not request.is_preview %}
|
{% if not request.is_preview %}
|
||||||
{% include "common/shareon.html" %}
|
{% include "common/shareon.html" %}
|
||||||
|
|
|
@ -56,6 +56,7 @@
|
||||||
{% for toc_item in page.table_of_contents %}
|
{% for toc_item in page.table_of_contents %}
|
||||||
{% include "common/toc-item.html" %}
|
{% include "common/toc-item.html" %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
{% block post_toc %}{% endblock %}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -11,7 +11,7 @@ from django.http import QueryDict
|
||||||
from django.http.request import HttpRequest
|
from django.http.request import HttpRequest
|
||||||
from django.utils.text import slugify
|
from django.utils.text import slugify
|
||||||
from django_cache_decorator import django_cache_decorator
|
from django_cache_decorator import django_cache_decorator
|
||||||
from metadata_parser import MetadataParser
|
from metadata_parser import MetadataParser, ParsedResult
|
||||||
from wagtail.models import Page, Site
|
from wagtail.models import Page, Site
|
||||||
from wagtail.models import get_page_models as get_wagtail_page_models
|
from wagtail.models import get_page_models as get_wagtail_page_models
|
||||||
|
|
||||||
|
@ -128,8 +128,13 @@ def get_ai_robots_txt() -> str:
|
||||||
|
|
||||||
|
|
||||||
@django_cache_decorator(time=21600)
|
@django_cache_decorator(time=21600)
|
||||||
def get_page_metadata(url: str) -> MetadataParser:
|
def get_page_metadata(url: str) -> ParsedResult:
|
||||||
return MetadataParser(url=url, search_head_only=True)
|
metadata = MetadataParser(url=url, search_head_only=True).parsed_result
|
||||||
|
|
||||||
|
# HACK: BeautifulSoup doesn't pickle nicely, and so can't be cached
|
||||||
|
metadata.soup = None
|
||||||
|
|
||||||
|
return metadata
|
||||||
|
|
||||||
|
|
||||||
def extend_query_params(url: str, params: dict[str, Any]) -> str:
|
def extend_query_params(url: str, params: dict[str, Any]) -> str:
|
||||||
|
|
|
@ -1,21 +1,16 @@
|
||||||
|
import lightningcss
|
||||||
from django.http import HttpRequest, HttpResponse
|
from django.http import HttpRequest, HttpResponse
|
||||||
from django.utils.datastructures import OrderedSet
|
|
||||||
from django.views.decorators.cache import cache_control
|
from django.views.decorators.cache import cache_control
|
||||||
from pygments.formatters.html import HtmlFormatter
|
from pygments.formatters.html import HtmlFormatter
|
||||||
|
|
||||||
|
|
||||||
@cache_control(max_age=3600)
|
@cache_control(max_age=3600)
|
||||||
def pygments_styles(request: HttpRequest) -> HttpResponse:
|
def pygments_styles(request: HttpRequest) -> HttpResponse:
|
||||||
default_styles = (
|
default_styles = HtmlFormatter(style="default").get_style_defs(
|
||||||
HtmlFormatter(style="default")
|
"html:not(.dark-mode) .highlight"
|
||||||
.get_style_defs("html:not(.dark-mode) .highlight")
|
|
||||||
.split("\n")
|
|
||||||
)
|
)
|
||||||
dark_styles = (
|
dark_styles = HtmlFormatter(style="monokai").get_style_defs(
|
||||||
HtmlFormatter(style="monokai")
|
"html.dark-mode .highlight"
|
||||||
.get_style_defs("html.dark-mode .highlight")
|
|
||||||
.split("\n")
|
|
||||||
)
|
|
||||||
return HttpResponse(
|
|
||||||
"".join(OrderedSet(default_styles + dark_styles)), content_type="text/css"
|
|
||||||
)
|
)
|
||||||
|
compressed = lightningcss.process_stylesheet(default_styles + dark_styles)
|
||||||
|
return HttpResponse(compressed, content_type="text/css")
|
||||||
|
|
Loading…
Reference in New Issue
Block a user