picata 0.0.4__py3-none-any.whl → 0.0.5__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- entrypoint.tsx +4 -3
- picata/apps.py +1 -1
- picata/templates/picata/base.html +3 -1
- picata/templatetags/kill_orphans.py +62 -0
- picata/templatetags/stringify.py +5 -2
- {picata-0.0.4.dist-info → picata-0.0.5.dist-info}/METADATA +1 -1
- {picata-0.0.4.dist-info → picata-0.0.5.dist-info}/RECORD +10 -9
- styles.sass +4 -2
- {picata-0.0.4.dist-info → picata-0.0.5.dist-info}/WHEEL +0 -0
- {picata-0.0.4.dist-info → picata-0.0.5.dist-info}/licenses/LICENSE.md +0 -0
entrypoint.tsx
CHANGED
@@ -167,12 +167,13 @@ function renderPageContents(): void {
|
|
167
167
|
const listStack: HTMLUListElement[] = [tocList];
|
168
168
|
let currentLevel = 1;
|
169
169
|
|
170
|
-
// Find all anchor-linked headings
|
170
|
+
// Find all anchor-linked headings inside articles
|
171
171
|
const headings = document.querySelectorAll<HTMLElement>(
|
172
|
-
"h1[id], h2[id], h3[id], h4[id], h5[id], h6[id]",
|
172
|
+
"article h1[id], article h2[id], article h3[id], article h4[id], article h5[id], article h6[id]",
|
173
173
|
);
|
174
|
+
|
174
175
|
headings.forEach((heading) => {
|
175
|
-
const headingLevel = parseInt(heading.tagName.substring(1));
|
176
|
+
const headingLevel = parseInt(heading.tagName.substring(1));
|
176
177
|
|
177
178
|
// Adjust the stack to match the heading level
|
178
179
|
while (headingLevel > currentLevel) {
|
picata/apps.py
CHANGED
@@ -28,6 +28,6 @@ class Config(AppConfig):
|
|
28
28
|
|
29
29
|
## Add anchored pillcrows to headings in designated pages
|
30
30
|
anchor_inserter = AnchorInserter(
|
31
|
-
root="
|
31
|
+
root=".//article", targets=".//h1 | .//h2 | .//h3 | .//h4 | .//h5 | .//h6"
|
32
32
|
)
|
33
33
|
HTMLProcessingMiddleware.add_transformer(anchor_inserter)
|
@@ -14,6 +14,8 @@
|
|
14
14
|
@font-face { font-family: 'Zilla Slab Highlight'; src: url("{% static 'fonts/ZillaSlabHighlight-Bold.ttf' %}") format("truetype"); font-weight: 700; font-style: normal; }
|
15
15
|
@font-face { font-family: 'Bitter'; src: url("{% static 'fonts/Bitter-Light.ttf' %}") format("truetype"); font-weight: 300; font-style: normal; }
|
16
16
|
@font-face { font-family: 'Bitter'; src: url("{% static 'fonts/Bitter-LightItalic.ttf' %}") format("truetype"); font-weight: 300; font-style: italic; }
|
17
|
+
@font-face { font-family: 'Bitter'; src: url("{% static 'fonts/Bitter-Bold.ttf' %}") format("truetype"); font-weight: 700; font-style: normal; }
|
18
|
+
@font-face { font-family: 'Bitter'; src: url("{% static 'fonts/Bitter-BoldItalic.ttf' %}") format("truetype"); font-weight: 700; font-style: italic; }}
|
17
19
|
@font-face { font-family: 'Fira Code'; src: url("{% static 'fonts/FiraCode-Light.ttf' %}") format("truetype"); font-weight: 300; font-style: normal; }
|
18
20
|
@font-face { font-family: 'Fira Code'; src: url("{% static 'fonts/FiraCode-SemiBold.ttf' %}") format("truetype"); font-weight: 600; font-style: normal; }
|
19
21
|
</style>
|
@@ -121,7 +123,7 @@
|
|
121
123
|
{% block content %}{% endblock %}
|
122
124
|
</main>
|
123
125
|
|
124
|
-
<footer>
|
126
|
+
<footer class="footer">
|
125
127
|
<div>
|
126
128
|
<p>© 2024 Ada Wright</p>
|
127
129
|
</div>
|
@@ -0,0 +1,62 @@
|
|
1
|
+
"""Filter to wrap the last two words of text in a span which prevents word-wrapping."""
|
2
|
+
|
3
|
+
from html.parser import HTMLParser
|
4
|
+
|
5
|
+
from django import template
|
6
|
+
from django.utils.html import escape
|
7
|
+
from django.utils.safestring import mark_safe
|
8
|
+
|
9
|
+
register = template.Library()
|
10
|
+
|
11
|
+
|
12
|
+
class KillOrphansParser(HTMLParser):
|
13
|
+
"""Parser that wraps the last two words of visible text in a span tag."""
|
14
|
+
|
15
|
+
result: list[str]
|
16
|
+
text_chunks: list[str]
|
17
|
+
|
18
|
+
def __init__(self) -> None:
|
19
|
+
"""Initialize the parser and result containers."""
|
20
|
+
super().__init__()
|
21
|
+
self.result = []
|
22
|
+
self.text_chunks = []
|
23
|
+
|
24
|
+
def handle_starttag(self, tag: str, attrs: list[tuple[str, str | None]]) -> None:
|
25
|
+
"""Handle start tags and store them."""
|
26
|
+
start_tag_text = self.get_starttag_text()
|
27
|
+
if start_tag_text is not None:
|
28
|
+
self.result.append(start_tag_text)
|
29
|
+
|
30
|
+
def handle_endtag(self, tag: str) -> None:
|
31
|
+
"""Handle end tags and store them."""
|
32
|
+
self.result.append(f"</{tag}>")
|
33
|
+
|
34
|
+
def handle_data(self, data: str) -> None:
|
35
|
+
"""Handle text data and store it."""
|
36
|
+
self.text_chunks.append(data)
|
37
|
+
self.result.append(data)
|
38
|
+
|
39
|
+
def get_wrapped_html(self) -> str:
|
40
|
+
"""Return HTML with the last two words wrapped in a span."""
|
41
|
+
full_text = "".join(self.text_chunks)
|
42
|
+
words = full_text.split()
|
43
|
+
|
44
|
+
if len(words) < 2: # noqa: PLR2004
|
45
|
+
return "".join(self.result)
|
46
|
+
|
47
|
+
wrapped_words = (
|
48
|
+
" ".join(words[:-2])
|
49
|
+
+ f' <span class="whitespace-nowrap">{escape(" ".join(words[-2:]))}</span>'
|
50
|
+
)
|
51
|
+
|
52
|
+
return mark_safe( # noqa: S308
|
53
|
+
"".join(wrapped_words if chunk in full_text else chunk for chunk in self.result)
|
54
|
+
)
|
55
|
+
|
56
|
+
|
57
|
+
@register.filter
|
58
|
+
def killorphans(value: str) -> str:
|
59
|
+
"""Wrap the last two words of visible text in a span tag."""
|
60
|
+
parser = KillOrphansParser()
|
61
|
+
parser.feed(value)
|
62
|
+
return parser.get_wrapped_html()
|
picata/templatetags/stringify.py
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
"""
|
1
|
+
"""Filter to transform Python types into human-readable strings."""
|
2
2
|
|
3
3
|
from django import template
|
4
4
|
|
@@ -8,7 +8,10 @@ register = template.Library()
|
|
8
8
|
@register.filter
|
9
9
|
def stringify(value: list, quote_style: str | None = None) -> str:
|
10
10
|
"""Convert a list of strings into a human-readable string with optional quoting."""
|
11
|
-
if not
|
11
|
+
if not value:
|
12
|
+
return ""
|
13
|
+
|
14
|
+
if not (isinstance(value, list | set | tuple)):
|
12
15
|
raise TypeError("The 'stringify' filter currently only supports lists.")
|
13
16
|
|
14
17
|
quote = "'" if quote_style == "single" else '"' if quote_style == "double" else ""
|
@@ -1,12 +1,12 @@
|
|
1
1
|
LICENSE.md,sha256=Bv8sMyZI5NI6DMrfiAvCwIFRLSfJkimLF2KVcUMteKU,1103
|
2
2
|
README.md,sha256=7IWS68r8WrNkr78JVuw4qKzTbZjv_g4rXw36mn-QfTI,2846
|
3
|
-
entrypoint.tsx,sha256=
|
3
|
+
entrypoint.tsx,sha256=rXpHc3syUVomgTkY-xRwzmhjVD-ZHeymOXPBeSQloh8,8835
|
4
4
|
manage.py,sha256=BkGWS_zb8HTvlrOxDiBaQoahUEJGCoV5ePhX-P6jIaw,426
|
5
5
|
pygments.sass,sha256=zbDYpWda3EoGmjoC3JshZy-_CECNf6WU9abYPF8EHms,6369
|
6
|
-
styles.sass,sha256=
|
6
|
+
styles.sass,sha256=SCG5WCr0jIGzdM_Vp_j_gKxFfcTsTwLWOmaEc6uMpvU,8501
|
7
7
|
components/HelloWorld.tsx,sha256=Kp7gvhGehfrX1mw0jgr2_D6AueFgqgfMYGkyQgvWekg,180
|
8
8
|
picata/__init__.py,sha256=ZCIoFQ_z3ias_sP4C77EU2IUJnyv4qR0xUdJ3PIdLLM,48
|
9
|
-
picata/apps.py,sha256=
|
9
|
+
picata/apps.py,sha256=kr6OBcYbBw9HCGG-PkoMTHR4QeyzJO8_KIWTljCTHRo,1255
|
10
10
|
picata/blocks.py,sha256=iVNxJM_uWlQIqZA-9Nao4svkG26oK5DQEogK0q_F2Po,5286
|
11
11
|
picata/log_utils.py,sha256=BRdB3PqpFx1XAhIyAzIOyQKiqrjbT3PBmkhH6-wAWJg,1555
|
12
12
|
picata/middleware.py,sha256=BbAifo--C4VYg1VhU8_qbdDcJUD9zYdbxU_9nqGpMa8,2067
|
@@ -46,7 +46,7 @@ picata/templates/picata/404.html,sha256=sN5q0-wM7UqU8zv_vdo8upRR1cnahiCFT92gHuyt
|
|
46
46
|
picata/templates/picata/500.html,sha256=1xvvK2uoiZKkc2EuVVnbfg69KmrCJUdplR0vvFtWvKo,369
|
47
47
|
picata/templates/picata/_post_list.html,sha256=JpvNAOGmupLQIC6lTyjoyNOyRGMUQwOqEvEaZgSPrsM,915
|
48
48
|
picata/templates/picata/article.html,sha256=dlrqrJLbQNMpaG6rgkN9oUZNXUFMnj8al8dG-LL8V5Y,801
|
49
|
-
picata/templates/picata/base.html,sha256=
|
49
|
+
picata/templates/picata/base.html,sha256=4QlQ7rS9ZDd_1-8_2awBs_6guKaKVjo731OfWd_zkVE,8476
|
50
50
|
picata/templates/picata/basic_page.html,sha256=-oVigKCOqNt-dnBKCW_pXpvs7aBu8LZCJW0i-XuyI-4,180
|
51
51
|
picata/templates/picata/dl_view.html,sha256=VMZqmA_Wy3BCT0pHP4mHtiZnnkNC--TmjBNHYuKyuTQ,501
|
52
52
|
picata/templates/picata/home_page.html,sha256=UmOONJuVC_YsscNHW-q9QnQX-VCS88_kl-pgLLgsHIo,642
|
@@ -63,11 +63,12 @@ picata/templates/picata/previews/theme_gallery.html,sha256=FzeaOpS9mcZpg5AwqBFbm
|
|
63
63
|
picata/templates/picata/tags/site_menu.html,sha256=5V7uo71FFsAPMoXo6NUMsOeu5eHpVor60iNgSt_QoR4,201
|
64
64
|
picata/templatetags/__init__.py,sha256=YNGfxmI00gewcJkkUlH219BHimHD_4p5Lz-zXPvgO-U,47
|
65
65
|
picata/templatetags/absolute_static.py,sha256=YpkPQhquvk2dRcnGy4g2yeLEBzRirOaQNs8AlGyM8tc,457
|
66
|
+
picata/templatetags/kill_orphans.py,sha256=d549iZdeaicslDm4atf5bC1QsRkHTgkp9xuMkMX14lQ,1965
|
66
67
|
picata/templatetags/menu_tags.py,sha256=QBv2HNA-phOedijP2YErBkO067oHZUD8Bh80SaGwjdY,1844
|
67
|
-
picata/templatetags/stringify.py,sha256=
|
68
|
+
picata/templatetags/stringify.py,sha256=XwSRNgaDlDm38TWOXcb8nl8NEttXXZ7C5_06znhv1ms,896
|
68
69
|
picata/typing/__init__.py,sha256=7qXco9cqvbveKX0Xprrc8DmgXa3MpkIQXtFsHDe77os,405
|
69
70
|
picata/typing/wagtail.py,sha256=V0n9GYYb_CM5ic54lcRtpN6lhN37-QdRzz2mGKm3Cwc,664
|
70
|
-
picata-0.0.
|
71
|
-
picata-0.0.
|
72
|
-
picata-0.0.
|
73
|
-
picata-0.0.
|
71
|
+
picata-0.0.5.dist-info/METADATA,sha256=m1fHFygjHAS6VJjttS73BVVosW3brx87N-XPpNR_16o,5092
|
72
|
+
picata-0.0.5.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
73
|
+
picata-0.0.5.dist-info/licenses/LICENSE.md,sha256=Bv8sMyZI5NI6DMrfiAvCwIFRLSfJkimLF2KVcUMteKU,1103
|
74
|
+
picata-0.0.5.dist-info/RECORD,,
|
styles.sass
CHANGED
@@ -9,6 +9,7 @@
|
|
9
9
|
@layer base
|
10
10
|
body
|
11
11
|
@apply text-base font-serif font-light
|
12
|
+
|
12
13
|
h1, h2, h3, h4, h5, h6
|
13
14
|
@apply font-heading font-normal
|
14
15
|
&:not(:first-child)
|
@@ -26,7 +27,9 @@
|
|
26
27
|
h6
|
27
28
|
@apply text-sm leading-relaxed
|
28
29
|
strong, b
|
29
|
-
@apply font-
|
30
|
+
@apply font-bold
|
31
|
+
em, i
|
32
|
+
@apply italic
|
30
33
|
code, pre
|
31
34
|
@apply font-mono font-light
|
32
35
|
&.strong
|
@@ -34,7 +37,6 @@
|
|
34
37
|
.highlight
|
35
38
|
@apply font-highlight font-bold
|
36
39
|
|
37
|
-
|
38
40
|
// Main page layout
|
39
41
|
html
|
40
42
|
scroll-behavior: smooth
|
File without changes
|
File without changes
|