skrift 0.1.0a14__py3-none-any.whl → 0.1.0a15__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4,6 +4,28 @@
4
4
  <meta charset="UTF-8">
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
6
  <title>{% block title %}{{ site_name() }}{% endblock %}</title>
7
+
8
+ {# SEO Meta Tags #}
9
+ {% block seo_meta %}
10
+ {% if seo_meta %}
11
+ {% if seo_meta.description %}<meta name="description" content="{{ seo_meta.description }}">{% endif %}
12
+ {% if seo_meta.robots %}<meta name="robots" content="{{ seo_meta.robots }}">{% endif %}
13
+ <link rel="canonical" href="{{ seo_meta.canonical_url }}">
14
+ {% endif %}
15
+ {% endblock %}
16
+
17
+ {# OpenGraph Tags #}
18
+ {% block og_meta %}
19
+ {% if og_meta %}
20
+ <meta property="og:title" content="{{ og_meta.title }}">
21
+ {% if og_meta.description %}<meta property="og:description" content="{{ og_meta.description }}">{% endif %}
22
+ {% if og_meta.image %}<meta property="og:image" content="{{ og_meta.image }}">{% endif %}
23
+ <meta property="og:url" content="{{ og_meta.url }}">
24
+ <meta property="og:site_name" content="{{ og_meta.site_name }}">
25
+ <meta property="og:type" content="{{ og_meta.type }}">
26
+ {% endif %}
27
+ {% endblock %}
28
+
7
29
  <link rel="preconnect" href="https://fonts.googleapis.com">
8
30
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
9
31
  <link href="https://fonts.googleapis.com/css2?family=Cinzel:wght@500;600&family=Lora:ital,wght@0,400;0,600;1,400;1,600&display=swap" rel="stylesheet">
@@ -33,10 +55,26 @@
33
55
  </header>
34
56
 
35
57
  <main class="container{% block main_class %}{% endblock %}">
36
- {% if flash %}
37
- <div class="flash-messages">
38
- <article role="alert">{{ flash }}</article>
39
- </div>
58
+ {# Enhanced flash messages with types #}
59
+ {% if flash_messages %}
60
+ <div class="flash-messages" role="status" aria-live="polite">
61
+ {% for msg in flash_messages %}
62
+ <article role="alert" class="flash flash-{{ msg.type.value }}" {% if msg.dismissible %}data-dismissible{% endif %}>
63
+ <span class="flash-message">{{ msg.message }}</span>
64
+ {% if msg.dismissible %}
65
+ <button type="button" class="flash-dismiss" aria-label="Dismiss">&times;</button>
66
+ {% endif %}
67
+ </article>
68
+ {% endfor %}
69
+ </div>
70
+ {# Backwards compatibility: old single flash string #}
71
+ {% elif flash %}
72
+ <div class="flash-messages" role="status" aria-live="polite">
73
+ <article role="alert" class="flash flash-info" data-dismissible>
74
+ <span class="flash-message">{{ flash }}</span>
75
+ <button type="button" class="flash-dismiss" aria-label="Dismiss">&times;</button>
76
+ </article>
77
+ </div>
40
78
  {% endif %}
41
79
 
42
80
  {% block content %}{% endblock %}
@@ -48,5 +86,21 @@
48
86
  </footer>
49
87
 
50
88
  {% block scripts %}{% endblock %}
89
+
90
+ <script>
91
+ // Flash message dismissal
92
+ document.querySelectorAll('.flash-dismiss').forEach(btn => {
93
+ btn.addEventListener('click', () => {
94
+ btn.closest('.flash').remove();
95
+ });
96
+ });
97
+ // Auto-dismiss success messages after 5 seconds
98
+ document.querySelectorAll('.flash-success[data-dismissible]').forEach(flash => {
99
+ setTimeout(() => {
100
+ flash.style.opacity = '0';
101
+ setTimeout(() => flash.remove(), 300);
102
+ }, 5000);
103
+ });
104
+ </script>
51
105
  </body>
52
106
  </html>
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: skrift
3
- Version: 0.1.0a14
3
+ Version: 0.1.0a15
4
4
  Summary: A lightweight async Python CMS for crafting modern websites
5
5
  Requires-Python: >=3.13
6
6
  Requires-Dist: advanced-alchemy>=0.26.0
@@ -35,6 +35,11 @@ A modern Litestar-powered content management framework with multi-provider OAuth
35
35
  - **Dynamic Controllers**: Load controllers from `app.yaml` configuration
36
36
  - **SQLAlchemy Integration**: Async database support with SQLite/PostgreSQL
37
37
  - **Client-Side Sessions**: Encrypted cookie sessions for horizontal scalability
38
+ - **Hook/Filter System**: WordPress-like extensibility with async support
39
+ - **SEO Metadata**: Built-in meta descriptions, OpenGraph tags, and robots directives
40
+ - **Content Scheduling**: Schedule pages to publish at a future date
41
+ - **Page Revisions**: Automatic content history with restore capability
42
+ - **Sitemap & Robots.txt**: Auto-generated with filter extensibility
38
43
 
39
44
  ## Quick Start
40
45
 
@@ -121,11 +126,17 @@ skrift/
121
126
  ├── skrift/ # Main Python package
122
127
  │ ├── asgi.py # Application factory
123
128
  │ ├── config.py # Settings management
124
- │ ├── controllers/ # Route handlers
129
+ │ ├── controllers/ # Route handlers (auth, web, sitemap)
125
130
  │ ├── admin/ # Admin panel
126
131
  │ ├── auth/ # RBAC and guards
127
132
  │ ├── db/ # Models and services
128
- │ ├── lib/ # Template resolver
133
+ ├── models/ # Page, User, Role, PageRevision
134
+ │ │ └── services/ # page_service, revision_service
135
+ │ ├── lib/ # Core utilities
136
+ │ │ ├── hooks.py # Hook/filter system
137
+ │ │ ├── seo.py # SEO metadata utilities
138
+ │ │ ├── flash.py # Enhanced flash messages
139
+ │ │ └── template.py # Template resolver
129
140
  │ └── setup/ # Setup wizard
130
141
  ├── templates/ # Jinja2 templates
131
142
  ├── static/ # Static assets
@@ -5,7 +5,7 @@ skrift/asgi.py,sha256=7uPvgsGMpZJyPOjIGxL9QlXTRLWh9uRAhcg-RdBS1c8,23355
5
5
  skrift/cli.py,sha256=aT-7pXvOuuZC-Eypx1h-xCiqaBKhIFjSqd5Ky_dHna0,4214
6
6
  skrift/config.py,sha256=ZDOrYgp6gC6fE1nEZgrAOouoykhRo2NZo5U1-WLdDSc,7862
7
7
  skrift/admin/__init__.py,sha256=x81Cj_ilVmv6slaMl16HHyT_AgrnLxKEWkS0RPa4V9s,289
8
- skrift/admin/controller.py,sha256=5ZDypvKHXLNDESsKNsdsH2E3Si5OqlpzttFl7Ot8aF0,15651
8
+ skrift/admin/controller.py,sha256=gSprerjhxqxaH2lHm8vbLuz-jslN553FpbKF7jwEm9Y,19607
9
9
  skrift/admin/navigation.py,sha256=VwttFoIUIJy5rONKIkJd5w4CNkUpeK22_OfLGHecN34,3382
10
10
  skrift/alembic/env.py,sha256=GaQx7D-3f0zVTV4YJNhN0GOfqHL99N4VBfMzjZJz0Bc,2673
11
11
  skrift/alembic/script.py.mako,sha256=MEqL-2qATlST9TAOeYgscMn1uy6HUS9NFvDgl93dMj8,635
@@ -16,28 +16,38 @@ skrift/alembic/versions/20260122_175637_a9c55348eae7_remove_page_type_column.py,
16
16
  skrift/alembic/versions/20260122_200000_add_settings_table.py,sha256=aG4pxp18fwonGAWt7EoT0XaiIEmu7zltSrj8e2a8QZU,1310
17
17
  skrift/alembic/versions/20260129_add_oauth_accounts.py,sha256=KPuzJ5J13FEbSbyziuB-nfO67i4cRgBeQnygn-uNQx8,5412
18
18
  skrift/alembic/versions/20260129_add_provider_metadata.py,sha256=prDfnYM0cODBSYb9xYqW5Dab2WDjHNkkEMRH-hI7BIA,846
19
+ skrift/alembic/versions/20260202_add_content_scheduling.py,sha256=b5eTIzVmHO5x9UJDwwqQG1gLDNxTzxY0qIl0xTkgZA4,1079
20
+ skrift/alembic/versions/20260202_add_page_ordering.py,sha256=4MdupLfmaM0oftbmRMGOUIDrT55yFCqQ8v9uCOofOZQ,941
21
+ skrift/alembic/versions/20260202_add_page_revisions.py,sha256=LKmxerftfWguGbIjveemnm9nEZ9ZjTm5rdEwoRiUVBY,2179
22
+ skrift/alembic/versions/20260202_add_seo_fields.py,sha256=rLnRY1RyckoVno6miUlTtgv_IceIFJRj3OS7aUVXcKE,1546
19
23
  skrift/auth/__init__.py,sha256=uHMqty3dgDSYlReVT96WhygzH6qNAWSVDWoxumzxmsA,1155
20
24
  skrift/auth/guards.py,sha256=QePajHsGnJ4R_hlhzblr5IoAgZcY5jzeZ64bJwDL9hM,4451
21
25
  skrift/auth/roles.py,sha256=Cvwv8v7Li6CJHhucTuzxRjaNmS530F9sbbQlCPRqhm4,3291
22
26
  skrift/auth/services.py,sha256=h6GTXdN5UMRYglnaFz4asMoutVkSSAyL3_Vt56N26pA,5441
23
27
  skrift/controllers/__init__.py,sha256=bVr0tsSGz7jBi002Lqd1AA1FQd7ZA_IagsqTKpiHiK0,147
24
28
  skrift/controllers/auth.py,sha256=ohYjBJiRa5RDQKUQjL3nR6lzm4uUZcfIgnF2G-QY5o8,21905
25
- skrift/controllers/web.py,sha256=vmoBS1u5G9gCBu65S49yqZn_WBKlmsqlcvX5tYXTKnE,2348
29
+ skrift/controllers/sitemap.py,sha256=Yfz2ElHrkZVMhAN5ixriU5RwEFJ713rS0Uezj90Bfts,3814
30
+ skrift/controllers/web.py,sha256=J-kbmzwJcKfiBvNbF8yR7GHGo0jhvWzY77YstJi_pcI,2968
26
31
  skrift/db/__init__.py,sha256=uSghyDFT2K4SFiEqUzdjCGzWpS-Oy6Sd1FUappau-v0,52
27
32
  skrift/db/base.py,sha256=QJplFj9235kZdScASEpvyNHln6YW2hqbHwJEYZ3OSsc,173
28
- skrift/db/models/__init__.py,sha256=wFF9YWe7rhIWIzRuMtAWVDcZdJsNcKnjfhKbLZw9JVs,341
33
+ skrift/db/models/__init__.py,sha256=DtgYPLs8rTLNFmZ0-HzD_8uhvaGRtayZCrxpMhAo88U,413
29
34
  skrift/db/models/oauth_account.py,sha256=fzmApdtrRYeEWLl35Y7H0YtF7CWjzrpG-lknBOuYRc8,1840
30
- skrift/db/models/page.py,sha256=CI5W2sWq0zbKHxfwH5TpmGdJ4zlTicckzpdZtaqjJVE,1019
35
+ skrift/db/models/page.py,sha256=pYMWBmQ7FfDiFcyBU3xV4kbpWboimZw5TZtVDOcr73o,2068
36
+ skrift/db/models/page_revision.py,sha256=S2TO8hR5ThPFRk1Ovdn3lFau6D2H6TLhfFX6ekp_OTI,1399
31
37
  skrift/db/models/role.py,sha256=VkwkF3XWemmFtkUpQRk6RTIBfcukrU-0PUPCeo8x834,1768
32
38
  skrift/db/models/setting.py,sha256=Am4HTyq2LFR408R6BZb--slys1xM8YLYq9HTq_gybD0,392
33
39
  skrift/db/models/user.py,sha256=kkR3h0CphUyvOGJOpiZH6Qp28LqW2OriwVTfybs7vuY,1338
34
40
  skrift/db/services/__init__.py,sha256=qAC24IPOYg6AampUWonmLeajljQRMwUw0lgXksQG6Nk,69
35
41
  skrift/db/services/oauth_service.py,sha256=1065tYGvrSer0X28GblibrSz2BjwVjl3tndXk1plthE,5208
36
- skrift/db/services/page_service.py,sha256=cXJ-urV7LjUDoVsT1P52f6wcOsur3T-pvqKkGG4xlvI,5246
37
- skrift/db/services/setting_service.py,sha256=eqFxukn8QFrDHQbaBILOLjP1nr34JPIPFT_NnhmeaTY,5613
38
- skrift/lib/__init__.py,sha256=Ew53SFcJcoohNF_FEDoDXsrks9cKZQonoaJAWyjXWMs,132
42
+ skrift/db/services/page_service.py,sha256=vVuxy7rNC9J6iCGFtmnt7Jrgo3cFm-vscdWcZ2RuMOQ,9830
43
+ skrift/db/services/revision_service.py,sha256=YBHeSac6V2_K3AKzDqup8fg0nys9nVLGOnLYD7GkxUQ,3701
44
+ skrift/db/services/setting_service.py,sha256=9u8LUMxnZAeSxf98_8GZXi5uioT4Jz-rYdIbs6wa4KE,5869
45
+ skrift/lib/__init__.py,sha256=XodsWJweaIpHtVkAHkEZHcCY8NSOBrUWxUQGZidP9l0,359
39
46
  skrift/lib/exceptions.py,sha256=p8ceLIQCc7agCwW6-mhBDAuMAMxZDcf9TDLC6PfztU4,5803
47
+ skrift/lib/flash.py,sha256=nWX7H8s218oBOE4d9kE6asHG_TNM4BbWJ7qrN65-Ewc,2921
48
+ skrift/lib/hooks.py,sha256=HsrOM-mVZSd1mSlNsj8YpfjJ7HwufDjFSnVUenmnwjA,8710
40
49
  skrift/lib/markdown.py,sha256=fPLUIAsmFXC64Os2RngQG7P2xRKBd1RO8fh7b5_gV1U,950
50
+ skrift/lib/seo.py,sha256=3fAfXn_7Jpq_OhINpcbQznixLcJTbaD-I86_Je2SFoo,2512
41
51
  skrift/lib/template.py,sha256=4_urkRfvth75yNeQ5TyGTHvkvs3vVef7TcwZx0k285k,4226
42
52
  skrift/setup/__init__.py,sha256=3VjFPMES5y0M5cQ9R4C1xazqiEPEDqTPjX9-3rBMXnA,478
43
53
  skrift/setup/config_writer.py,sha256=YFH3FVjXN7Rum2fzGVPAQRkjdc9b0bHECDqMKYiEkhg,6347
@@ -45,8 +55,8 @@ skrift/setup/controller.py,sha256=v0Ey8T7ptJ5A3vOqQ1TUAXH1bQwA0288J5uyUWMihsw,34
45
55
  skrift/setup/middleware.py,sha256=Nai8ZG2vHldngmAhq7kWzAwKRNcP5tHKhJHa5dCh404,2941
46
56
  skrift/setup/providers.py,sha256=0BFKB6168NcmtXxFF6ofHgEDMQD2FbXkexsqrARVtDI,7967
47
57
  skrift/setup/state.py,sha256=RMe9LtIjzDoOm9u-Nk5-KAnr_JBiQIjWDpTP9E30ezc,9304
48
- skrift/static/css/style.css,sha256=-Ijp4PCugWzhHhtZTaRUAITHJDW-0AsbNpDCFI1njVQ,20943
49
- skrift/templates/base.html,sha256=4bg4s4VdES0dSvhJYLgrfrN26ynqeq1-3jyKPkWWVWk,2065
58
+ skrift/static/css/style.css,sha256=6in8KjmwythfQV9pGt-uSCJCoHG1OijrdDOOad7oYBk,22978
59
+ skrift/templates/base.html,sha256=s6gylukPyBvb9StgNz8MRZr4h3QT3C8GTMiwOu23nC0,4421
50
60
  skrift/templates/error-404.html,sha256=sJrDaF3Or3Nyki8mxo3wBxLLzgy4wkB9p9wdS8pRA6k,409
51
61
  skrift/templates/error-500.html,sha256=MR0wJ1JKLqdmdvsoJbQnZxLkxDPE59LrlbtVPKLM8-A,401
52
62
  skrift/templates/error.html,sha256=tg45Hj0wNc9QiZKBVVQ2WsqDiAkByXZnuehTdJPclXc,415
@@ -54,8 +64,9 @@ skrift/templates/index.html,sha256=lzZlnoZ2luY__OtRVa61mpQIgcopAbkKa2rS9XRfRlI,1
54
64
  skrift/templates/page.html,sha256=aSTypibx86SzIhO7GTff8XXVrW8D-XbHNaTo_UT31oc,770
55
65
  skrift/templates/admin/admin.html,sha256=8sErpGKedl7Hf_CMeu53bUEHptH1FqdBX9LT3z-1HcU,454
56
66
  skrift/templates/admin/base.html,sha256=JX1MPw9XTY8jCT2M6iHUwEj8NPNOdZPca2cDUEs9kfQ,659
57
- skrift/templates/admin/pages/edit.html,sha256=s-uZ4BYG7BdnWYTBSS1mr5aFL8XfT8h-KNiSIraWmHw,1322
58
- skrift/templates/admin/pages/list.html,sha256=LYh1vEwSHkyXihjcy5PIo33iA7UeIxprw4Gsn1WZMm4,2185
67
+ skrift/templates/admin/pages/edit.html,sha256=WqA1xYg5ZbDmH77wuu-8pvxsQ0scS6QpYXlzrLKxAj8,3859
68
+ skrift/templates/admin/pages/list.html,sha256=KHjqIQMNV1Ts6Fgx9p_waiGOb9lVcAgLCMmomKAQoeA,2602
69
+ skrift/templates/admin/pages/revisions.html,sha256=hthxdcKqz_DUHzky_5dn6cDEsZWR49W2sqKTiJjhVpA,2075
59
70
  skrift/templates/admin/settings/site.html,sha256=xHZCZGj9XqyLKCe2eoBlpI3oFIx5VoG_5FP-VAF2mz4,1516
60
71
  skrift/templates/admin/users/list.html,sha256=9GWql1la5Srm-OOgooHR9Eouk7ZL66K_FXY6HAAB5lA,1732
61
72
  skrift/templates/admin/users/roles.html,sha256=pos-ZM-gXYCN_D8DZpzwEBEm_WvmOKMMPz-3xJqs7nY,1473
@@ -69,7 +80,7 @@ skrift/templates/setup/configuring.html,sha256=2KHW9h2BrJgL_kO5IizbAYs4pnFLyRf76
69
80
  skrift/templates/setup/database.html,sha256=gU4-315-QraHa2Eq4Fh3b55QpOM2CkJzh27_Yz13frA,5495
70
81
  skrift/templates/setup/restart.html,sha256=GHg31F_e2uLFhWUzJoalk0Y0oYLqsFWyZXWKX3mblbY,1355
71
82
  skrift/templates/setup/site.html,sha256=PSOH-q1-ZBl47iSW9-Ad6lEfJn_fzdGD3Pk4vb3xgK4,1680
72
- skrift-0.1.0a14.dist-info/METADATA,sha256=unD0pS4u31RZprH6rOeGVZJ_zA565aw7wTFxXzG91Go,6511
73
- skrift-0.1.0a14.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
74
- skrift-0.1.0a14.dist-info/entry_points.txt,sha256=uquZ5Mumqr0xwYTpTcNiJtFSITGfF6_QCCy2DZJSZig,42
75
- skrift-0.1.0a14.dist-info/RECORD,,
83
+ skrift-0.1.0a15.dist-info/METADATA,sha256=6_eCcfYQ2K5uH_acqd3Q3FmEby0a1Yx710xIiEBa3rs,7267
84
+ skrift-0.1.0a15.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
85
+ skrift-0.1.0a15.dist-info/entry_points.txt,sha256=uquZ5Mumqr0xwYTpTcNiJtFSITGfF6_QCCy2DZJSZig,42
86
+ skrift-0.1.0a15.dist-info/RECORD,,