-
Notifications
You must be signed in to change notification settings - Fork 19
/
Copy pathblocks.py
68 lines (53 loc) · 2.5 KB
/
blocks.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
import re
from django.core.exceptions import ValidationError
from django.utils.safestring import mark_safe
from wagtail.core.blocks import RichTextBlock
from wagtail.core.models import Page
FIND_FOOTNOTE_TAG = re.compile(r'<footnote id="(.*?)">.*?</footnote>')
class RichTextBlockWithFootnotes(RichTextBlock):
"""
Rich Text block that renders footnotes in the format
'<footnote id="long-id">short-id</footnote>' as anchor elements. It also
adds the Footnote object to the 'page' object for later use. It uses
'page' because variables added to 'context' do not persist into the
final template context.
"""
def __init__(self, **kwargs):
super().__init__(**kwargs)
if not self.features:
self.features = []
if "footnotes" not in self.features:
self.features.append("footnotes")
def replace_footnote_tags(self, value, html, context=None):
if context is None:
new_context = self.get_context(value)
else:
new_context = self.get_context(value, parent_context=dict(context))
if not isinstance(new_context.get("page"), Page):
return html
page = new_context["page"]
if not hasattr(page, "footnotes_list"):
page.footnotes_list = []
self.footnotes = {footnote.uuid: footnote for footnote in page.footnotes.all()}
def replace_tag(match):
try:
index = self.process_footnote(match.group(1), page)
except (KeyError, ValidationError):
return ""
else:
return f'<a href="#footnote-{index}" id="footnote-source-{index}"><sup>[{index}]</sup></a>'
return mark_safe(FIND_FOOTNOTE_TAG.sub(replace_tag, html))
def render(self, value, context=None):
if not self.get_template(context=context):
return self.render_basic(value, context=context)
html = super().render(value, context=context)
return self.replace_footnote_tags(value, html, context=context)
def render_basic(self, value, context=None):
html = super().render_basic(value, context)
return self.replace_footnote_tags(value, html, context=context)
def process_footnote(self, footnote_id, page):
footnote = self.footnotes[footnote_id]
if footnote not in page.footnotes_list:
page.footnotes_list.append(footnote)
# Add 1 to the index as footnotes are indexed starting at 1 not 0.
return page.footnotes_list.index(footnote) + 1