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 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)); // Extract the heading level (e.g., "1" for "H1")
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="//main/article", targets=".//h1 | .//h2 | .//h3 | .//h4 | .//h5 | .//h6"
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>&copy; 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()
@@ -1,4 +1,4 @@
1
- """Template tags to transform Python types into human-readable strings."""
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 isinstance(value, list):
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,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: picata
3
- Version: 0.0.4
3
+ Version: 0.0.5
4
4
  Summary: Ada's Wagtail-based CMS & blog
5
5
  Project-URL: Documentation, https://github.com/hipikat/picata#readme
6
6
  Project-URL: Issues, https://github.com/hipikat/picata/issues
@@ -1,12 +1,12 @@
1
1
  LICENSE.md,sha256=Bv8sMyZI5NI6DMrfiAvCwIFRLSfJkimLF2KVcUMteKU,1103
2
2
  README.md,sha256=7IWS68r8WrNkr78JVuw4qKzTbZjv_g4rXw36mn-QfTI,2846
3
- entrypoint.tsx,sha256=Tk6L2rCk0KrE5kaSL0GFuL3S19yG-BsUgvNAGe32uy8,8820
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=4Jb-Gxn9AP09pZzwLlCGGfeacCyrncpJAOCYcy-dyB4,8486
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=r5UQNm2CDP5tq22vQ_j6KuD6AGU3ODkvEQUeRvzJW0k,1259
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=QdmW5jgdUQleFjmWqTHVN9WYGpe8URMbEUQShClT_3c,8152
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=QxStfcCgn29IGinH_bdsZoaiTLL7pz30ObDitlagecs,850
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.4.dist-info/METADATA,sha256=tNPsx50nN3r9bQ1Xn9pJTvVdNdCZdIZHkRsqsbKyh0g,5092
71
- picata-0.0.4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
72
- picata-0.0.4.dist-info/licenses/LICENSE.md,sha256=Bv8sMyZI5NI6DMrfiAvCwIFRLSfJkimLF2KVcUMteKU,1103
73
- picata-0.0.4.dist-info/RECORD,,
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-serif font-bold
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