Add anchor links to headers

This commit is contained in:
Jake Howard 2022-07-01 09:25:57 +01:00
parent 1c7917cb86
commit 03e9da57a1
Signed by: jake
GPG key ID: 57AFB45680EDD477
4 changed files with 33 additions and 5 deletions

View file

@ -1,6 +1,16 @@
section.content {
font-size: 1.25rem;
padding-top: 0.5rem;
h2,
h3,
h4,
h5,
h6 {
.heading-anchor {
margin-right: 0.5rem;
}
}
}
.content-details {

View file

@ -10,7 +10,7 @@ from wagtail.images import get_image_model_string
from wagtail.models import Page
from .streamfield import get_blocks, get_html, get_word_count, truncate_streamfield
from .utils import TocEntry, get_table_of_contents
from .utils import TocEntry, add_heading_anchors, get_table_of_contents
class BasePage(Page):
@ -68,6 +68,10 @@ class BaseContentMixin(models.Model):
def summary(self) -> str:
return truncate_streamfield(self.body, 50)
@cached_property
def body_html(self):
return add_heading_anchors(str(self.body))
class ContentPage(BasePage, BaseContentMixin): # type: ignore[misc]
subpage_types: list[Any] = []

View file

@ -1,13 +1,13 @@
{% extends "wagtail_base.html" %}
{% load wagtailcore_tags static %}
{% load static %}
{% block content %}
{% include "common/hero.html" %}
<section class="container content">
{% include_block page.body %}
{{ page.body_html|safe }}
</section>
{% endblock %}

View file

@ -5,9 +5,12 @@ from typing import Type
from bs4 import BeautifulSoup
from django.conf import settings
from django.http.request import HttpRequest
from django.utils.text import slugify
from wagtail.models import Page
from wagtail.models import get_page_models as get_wagtail_page_models
HEADER_TAGS = ["h2", "h3", "h4", "h5", "h6"]
@dataclass
class TocEntry:
@ -20,10 +23,10 @@ class TocEntry:
def get_table_of_contents(html: str) -> list[TocEntry]:
soup = BeautifulSoup(html, "lxml")
headings = soup.find_all(["h2", "h3", "h4", "h5", "h6"])
headings = soup.find_all(HEADER_TAGS)
heading_levels = [
TocEntry(tag.text, tag.text, int(tag.name[1]), []) for tag in headings
TocEntry(tag.text, slugify(tag.text), int(tag.name[1]), []) for tag in headings
]
# Abort if there are no headings
@ -53,6 +56,17 @@ def get_table_of_contents(html: str) -> list[TocEntry]:
return root.children
def add_heading_anchors(html: str) -> str:
soup = BeautifulSoup(html, "lxml")
for tag in soup.find_all(HEADER_TAGS):
slug = slugify(tag.text)
anchor = soup.new_tag("a", href="#" + slug, id=slug)
anchor.string = "#"
anchor.attrs["class"] = "heading-anchor"
tag.insert(0, anchor)
return str(soup)
def get_page_models() -> list[Type[Page]]:
page_models = get_wagtail_page_models().copy()
page_models.remove(Page)