picata 0.0.3__tar.gz → 0.0.5__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. {picata-0.0.3 → picata-0.0.5}/.gitignore +1 -0
  2. {picata-0.0.3 → picata-0.0.5}/PKG-INFO +1 -2
  3. {picata-0.0.3 → picata-0.0.5}/entrypoint.tsx +4 -3
  4. {picata-0.0.3 → picata-0.0.5}/picata/apps.py +1 -1
  5. {picata-0.0.3 → picata-0.0.5}/picata/templates/picata/3_column.html +1 -1
  6. {picata-0.0.3 → picata-0.0.5}/picata/templates/picata/404.html +1 -1
  7. {picata-0.0.3 → picata-0.0.5}/picata/templates/picata/article.html +1 -1
  8. {picata-0.0.3 → picata-0.0.5}/picata/templates/picata/base.html +5 -3
  9. {picata-0.0.3 → picata-0.0.5}/picata/templates/picata/basic_page.html +1 -1
  10. {picata-0.0.3 → picata-0.0.5}/picata/templates/picata/dl_view.html +1 -1
  11. {picata-0.0.3 → picata-0.0.5}/picata/templates/picata/home_page.html +1 -1
  12. {picata-0.0.3 → picata-0.0.5}/picata/templates/picata/post_listing.html +2 -2
  13. {picata-0.0.3 → picata-0.0.5}/picata/templates/picata/previews/3col.html +1 -1
  14. {picata-0.0.3 → picata-0.0.5}/picata/templates/picata/previews/dl.html +1 -1
  15. {picata-0.0.3 → picata-0.0.5}/picata/templates/picata/previews/split.html +1 -1
  16. {picata-0.0.3 → picata-0.0.5}/picata/templates/picata/previews/theme_gallery.html +1 -1
  17. {picata-0.0.3 → picata-0.0.5}/picata/templates/picata/search_results.html +2 -2
  18. {picata-0.0.3 → picata-0.0.5}/picata/templates/picata/split_view.html +1 -1
  19. picata-0.0.5/picata/templates/picata/tags/site_menu.html +5 -0
  20. picata-0.0.5/picata/templatetags/kill_orphans.py +62 -0
  21. {picata-0.0.3 → picata-0.0.5}/picata/templatetags/stringify.py +5 -2
  22. {picata-0.0.3 → picata-0.0.5}/pyproject.toml +1 -2
  23. {picata-0.0.3 → picata-0.0.5}/styles.sass +4 -2
  24. picata-0.0.3/picata/templates/picata/tags/site_menu.html +0 -8
  25. {picata-0.0.3 → picata-0.0.5}/LICENSE.md +0 -0
  26. {picata-0.0.3 → picata-0.0.5}/README.md +0 -0
  27. {picata-0.0.3 → picata-0.0.5}/components/HelloWorld.tsx +0 -0
  28. {picata-0.0.3 → picata-0.0.5}/manage.py +0 -0
  29. {picata-0.0.3 → picata-0.0.5}/picata/__init__.py +0 -0
  30. {picata-0.0.3 → picata-0.0.5}/picata/blocks.py +0 -0
  31. {picata-0.0.3 → picata-0.0.5}/picata/helpers/__init__.py +0 -0
  32. {picata-0.0.3 → picata-0.0.5}/picata/helpers/wagtail.py +0 -0
  33. {picata-0.0.3 → picata-0.0.5}/picata/log_utils.py +0 -0
  34. {picata-0.0.3 → picata-0.0.5}/picata/middleware.py +0 -0
  35. {picata-0.0.3 → picata-0.0.5}/picata/migrations/0001_initial.py +0 -0
  36. {picata-0.0.3 → picata-0.0.5}/picata/migrations/__init__.py +0 -0
  37. {picata-0.0.3 → picata-0.0.5}/picata/models.py +0 -0
  38. {picata-0.0.3 → picata-0.0.5}/picata/settings/__init__.py +0 -0
  39. {picata-0.0.3 → picata-0.0.5}/picata/settings/base.py +0 -0
  40. {picata-0.0.3 → picata-0.0.5}/picata/settings/dev.py +0 -0
  41. {picata-0.0.3 → picata-0.0.5}/picata/settings/mypy.py +0 -0
  42. {picata-0.0.3 → picata-0.0.5}/picata/settings/prod.py +0 -0
  43. {picata-0.0.3 → picata-0.0.5}/picata/settings/test.py +0 -0
  44. {picata-0.0.3 → picata-0.0.5}/picata/static/picata/ada-profile.jpg +0 -0
  45. {picata-0.0.3 → picata-0.0.5}/picata/static/picata/ada-social-bear.jpg +0 -0
  46. {picata-0.0.3 → picata-0.0.5}/picata/static/picata/favicon.ico +0 -0
  47. {picata-0.0.3 → picata-0.0.5}/picata/static/picata/fonts/Bitter-Light.ttf +0 -0
  48. {picata-0.0.3 → picata-0.0.5}/picata/static/picata/fonts/Bitter-LightItalic.ttf +0 -0
  49. {picata-0.0.3 → picata-0.0.5}/picata/static/picata/fonts/FiraCode-Light.ttf +0 -0
  50. {picata-0.0.3 → picata-0.0.5}/picata/static/picata/fonts/FiraCode-SemiBold.ttf +0 -0
  51. {picata-0.0.3 → picata-0.0.5}/picata/static/picata/fonts/Sacramento-Regular.ttf +0 -0
  52. {picata-0.0.3 → picata-0.0.5}/picata/static/picata/fonts/ZillaSlab-Bold.ttf +0 -0
  53. {picata-0.0.3 → picata-0.0.5}/picata/static/picata/fonts/ZillaSlab-BoldItalic.ttf +0 -0
  54. {picata-0.0.3 → picata-0.0.5}/picata/static/picata/fonts/ZillaSlab-Light.ttf +0 -0
  55. {picata-0.0.3 → picata-0.0.5}/picata/static/picata/fonts/ZillaSlab-LightItalic.ttf +0 -0
  56. {picata-0.0.3 → picata-0.0.5}/picata/static/picata/fonts/ZillaSlabHighlight-Bold.ttf +0 -0
  57. {picata-0.0.3 → picata-0.0.5}/picata/static/picata/icons.svg +0 -0
  58. {picata-0.0.3 → picata-0.0.5}/picata/templates/picata/500.html +0 -0
  59. {picata-0.0.3 → picata-0.0.5}/picata/templates/picata/_post_list.html +0 -0
  60. {picata-0.0.3 → picata-0.0.5}/picata/templates/picata/blocks/icon_link_item.html +0 -0
  61. {picata-0.0.3 → picata-0.0.5}/picata/templates/picata/blocks/icon_link_list.html +0 -0
  62. {picata-0.0.3 → picata-0.0.5}/picata/templates/picata/blocks/icon_link_list_stream.html +0 -0
  63. {picata-0.0.3 → picata-0.0.5}/picata/templatetags/__init__.py +0 -0
  64. {picata-0.0.3 → picata-0.0.5}/picata/templatetags/absolute_static.py +0 -0
  65. {picata-0.0.3 → picata-0.0.5}/picata/templatetags/menu_tags.py +0 -0
  66. {picata-0.0.3 → picata-0.0.5}/picata/transformers.py +0 -0
  67. {picata-0.0.3 → picata-0.0.5}/picata/typing/__init__.py +0 -0
  68. {picata-0.0.3 → picata-0.0.5}/picata/typing/wagtail.py +0 -0
  69. {picata-0.0.3 → picata-0.0.5}/picata/urls.py +0 -0
  70. {picata-0.0.3 → picata-0.0.5}/picata/validators.py +0 -0
  71. {picata-0.0.3 → picata-0.0.5}/picata/views.py +0 -0
  72. {picata-0.0.3 → picata-0.0.5}/picata/wagtail_hooks.py +0 -0
  73. {picata-0.0.3 → picata-0.0.5}/picata/wsgi.py +0 -0
  74. {picata-0.0.3 → picata-0.0.5}/pygments.sass +0 -0
@@ -18,6 +18,7 @@ static/
18
18
  !src/picata/static/
19
19
  src/db.sqlite3
20
20
  snapshots/*.tgz
21
+ emergency_backup.dump
21
22
 
22
23
  logs/
23
24
  *.log
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: picata
3
- Version: 0.0.3
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
@@ -39,7 +39,6 @@ Classifier: Programming Language :: Python
39
39
  Classifier: Programming Language :: Python :: 3.13
40
40
  Classifier: Programming Language :: Python :: Implementation :: CPython
41
41
  Requires-Python: >=3.13
42
- Requires-Dist: gunicorn~=23.0.0
43
42
  Requires-Dist: lxml~=5.3.0
44
43
  Requires-Dist: psutil~=6.1.0
45
44
  Requires-Dist: psycopg~=3.2.3
@@ -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) {
@@ -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)
@@ -1,4 +1,4 @@
1
- {% extends "base.html" %}
1
+ {% extends "picata/base.html" %}
2
2
  {% comment %}
3
3
  Three-column layout, at `lg`-up, with a 25% aside, 50% article, and 25% nav.
4
4
 
@@ -1,4 +1,4 @@
1
- {% extends "base.html" %}
1
+ {% extends "picata/base.html" %}
2
2
 
3
3
  {% block title %}Page not found{% endblock %}
4
4
 
@@ -1,4 +1,4 @@
1
- {% extends "3_column.html" %}
1
+ {% extends "picata/3_column.html" %}
2
2
  {% load wagtailcore_tags %}
3
3
 
4
4
  {% block main_classes %}{{ block.super }} article{% endblock %}
@@ -3,7 +3,7 @@
3
3
  <head>
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, viewport-fit=cover" />
6
- <title>{% block document_title %}{% if title %}{{ title }} · {% endif %}[Example Site]{% endblock %}</title>
6
+ <title>{% block document_title %}{% if title %}{{ title }} · {% endif %}hpk.io{% endblock %}</title>
7
7
 
8
8
  <style>
9
9
  @font-face { font-family: 'Sacramento'; src: url("{% static 'fonts/Sacramento-Regular.ttf' %}") format("truetype"); font-weight: 400; font-style: normal; }
@@ -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>
@@ -25,7 +27,7 @@
25
27
 
26
28
  <meta property="og:title" content="{% block og_title %}Hpk.io{% endblock %}">
27
29
  <meta property="og:description" content="{% block og_description %}Ada Wrights's website - Hpk.io{% endblock %}">
28
- <meta property="og:image" content="{% block og_image %}{% if settings.picata.SocialSettings.default_social_image %}{{ request.scheme }}://{{ request.get_host }}/{% image_url settings.hpk.SocialSettings.default_social_image 'fill-1200x630' %}{% else %}{% absolute_static 'ada-social-bear.jpg' %}{% endif %}{% endblock %}">
30
+ <meta property="og:image" content="{% block og_image %}{% if settings.picata.SocialSettings.default_social_image %}{{ request.scheme }}://{{ request.get_host }}/{% image_url settings.picata.SocialSettings.default_social_image 'fill-1200x630' %}{% else %}{% absolute_static 'ada-social-bear.jpg' %}{% endif %}{% endblock %}">
29
31
  <meta property="og:url" content="{{ request.build_absolute_uri }}">
30
32
  <meta property="og:type" content="{% block og_type %}website{% endblock %}">
31
33
 
@@ -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>
@@ -1,4 +1,4 @@
1
- {% extends "base.html" %}
1
+ {% extends "picata/base.html" %}
2
2
  {% load wagtailcore_tags %}
3
3
 
4
4
  {% block content %}
@@ -1,4 +1,4 @@
1
- {% extends "base.html" %}
1
+ {% extends "picata/base.html" %}
2
2
  {% comment %}
3
3
  Two-column layout (25%/75%), with a 2px line between the columns.
4
4
 
@@ -1,4 +1,4 @@
1
- {% extends "split_view.html" %}
1
+ {% extends "picata/split_view.html" %}
2
2
  {% load wagtailcore_tags %}
3
3
  {% comment %}
4
4
  Template for the HomePage class, utilising a split-view page layout.
@@ -1,4 +1,4 @@
1
- {% extends "dl_view.html" %}
1
+ {% extends "picata/dl_view.html" %}
2
2
  {% load wagtailcore_tags %}
3
3
 
4
4
  {% block main_classes %}{{ block.super }} post-list{% endblock %}
@@ -10,7 +10,7 @@
10
10
  </dd>
11
11
 
12
12
  {% for year, posts in posts_by_year.items %}
13
- {% include "_post_list.html" with posts=posts year=year %}
13
+ {% include "picata/_post_list.html" with posts=posts year=year %}
14
14
  {% endfor %}
15
15
 
16
16
  </dl>
@@ -1,4 +1,4 @@
1
- {% extends "3_column.html" %}
1
+ {% extends "picata/3_column.html" %}
2
2
 
3
3
  {% block title %}Home{% endblock %}
4
4
 
@@ -1,4 +1,4 @@
1
- {% extends "dl_view.html" %}
1
+ {% extends "picata/dl_view.html" %}
2
2
 
3
3
  {% block definitions %}
4
4
  <dt><p><a href="#what-is-lorem-ipsum">What is Lorem Ipsum?</a></p></dt>
@@ -1,4 +1,4 @@
1
- {% extends "split_view.html" %}
1
+ {% extends "picata/split_view.html" %}
2
2
 
3
3
  {% block content %}
4
4
  <div><p><a href="#what-is-lorem-ipsum">What is Lorem Ipsum?</a></p></div>
@@ -1,4 +1,4 @@
1
- {% extends "article.html" %}
1
+ {% extends "picata/article.html" %}
2
2
  {% load wagtailimages_tags %}
3
3
 
4
4
 
@@ -1,4 +1,4 @@
1
- {% extends "dl_view.html" %}
1
+ {% extends "picata/dl_view.html" %}
2
2
  {% load wagtailcore_tags stringify %}
3
3
 
4
4
  {% block main_classes %}{{ block.super }} post-list search-results{% endblock %}
@@ -22,7 +22,7 @@
22
22
  {% endif %}
23
23
  </dd>
24
24
 
25
- {% include "_post_list.html" with posts=pages %}
25
+ {% include "picata/_post_list.html" with posts=pages %}
26
26
 
27
27
  </dl>
28
28
  {% endblock %}
@@ -1,4 +1,4 @@
1
- {% extends "base.html" %}
1
+ {% extends "picata/base.html" %}
2
2
  {% comment %}
3
3
  Two-column layout (50%/50%), with a 2px line between the columns.
4
4
 
@@ -0,0 +1,5 @@
1
+ {% for page in menu_pages %}
2
+ <a {% if page == current_section %}class="current" {% endif %}href="{{ page.url }}">
3
+ {{ page.title }}{% if not page.live %} (not live){% endif %}
4
+ </a>
5
+ {% endfor %}
@@ -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 ""
@@ -9,7 +9,7 @@ build-backend = "hatchling.build"
9
9
 
10
10
  [project]
11
11
  name = "picata"
12
- version = "0.0.3"
12
+ version = "0.0.5"
13
13
  description = "Ada's Wagtail-based CMS & blog"
14
14
  keywords = ["cms", "blog", "django", "wagtail"]
15
15
  readme = "README.md"
@@ -26,7 +26,6 @@ classifiers = [
26
26
  ]
27
27
  dependencies = [
28
28
  "wagtail~=6.2",
29
- "gunicorn~=23.0.0",
30
29
  "psycopg~=3.2.3",
31
30
  "psutil~=6.1.0",
32
31
  "python-slugify~=8.0.4",
@@ -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
@@ -1,8 +0,0 @@
1
- <nav>
2
- <a href="{{ root_page.url }}">{{ root_page.title }}</a>
3
- {% for page in menu_pages %}
4
- <a href="{{ page.url }}">
5
- {{ page.title }}{% if not page.live %} (not live){% endif %}
6
- </a>
7
- {% endfor %}
8
- </nav>
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes