moosey-cms 0.4.0__tar.gz → 0.6.0__tar.gz
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.
- {moosey_cms-0.4.0 → moosey_cms-0.6.0}/PKG-INFO +3 -1
- {moosey_cms-0.4.0 → moosey_cms-0.6.0}/README.md +2 -0
- moosey_cms-0.6.0/docs/filters.md +184 -0
- {moosey_cms-0.4.0 → moosey_cms-0.6.0}/pyproject.toml +1 -1
- {moosey_cms-0.4.0 → moosey_cms-0.6.0}/src/moosey_cms/filters.py +40 -1
- {moosey_cms-0.4.0 → moosey_cms-0.6.0}/src/moosey_cms/hot_reload_script.py +8 -3
- {moosey_cms-0.4.0 → moosey_cms-0.6.0}/src/moosey_cms/main.py +25 -0
- moosey_cms-0.4.0/src/moosey_cms/.python-version +0 -1
- moosey_cms-0.4.0/src/moosey_cms/py.typed +0 -0
- moosey_cms-0.4.0/src/moosey_cms/pyproject.toml +0 -28
- {moosey_cms-0.4.0 → moosey_cms-0.6.0}/.gitignore +0 -0
- {moosey_cms-0.4.0 → moosey_cms-0.6.0}/.python-version +0 -0
- {moosey_cms-0.4.0 → moosey_cms-0.6.0}/example/assets/example-1.jpeg +0 -0
- {moosey_cms-0.4.0 → moosey_cms-0.6.0}/example/assets/example-2.jpeg +0 -0
- {moosey_cms-0.4.0 → moosey_cms-0.6.0}/example/content/about.md +0 -0
- {moosey_cms-0.4.0 → moosey_cms-0.6.0}/example/content/index.md +0 -0
- {moosey_cms-0.4.0 → moosey_cms-0.6.0}/example/content/pages/features.md +0 -0
- {moosey_cms-0.4.0 → moosey_cms-0.6.0}/example/content/posts/building-modern-apps.md +0 -0
- {moosey_cms-0.4.0 → moosey_cms-0.6.0}/example/content/posts/index.md +0 -0
- {moosey_cms-0.4.0 → moosey_cms-0.6.0}/example/main.py +0 -0
- {moosey_cms-0.4.0 → moosey_cms-0.6.0}/example/templates/404.html +0 -0
- {moosey_cms-0.4.0 → moosey_cms-0.6.0}/example/templates/components/sidebar.html +0 -0
- {moosey_cms-0.4.0 → moosey_cms-0.6.0}/example/templates/index.html +0 -0
- {moosey_cms-0.4.0 → moosey_cms-0.6.0}/example/templates/layout/base.html +0 -0
- {moosey_cms-0.4.0 → moosey_cms-0.6.0}/example/templates/page.html +0 -0
- {moosey_cms-0.4.0 → moosey_cms-0.6.0}/example/templates/post.html +0 -0
- {moosey_cms-0.4.0 → moosey_cms-0.6.0}/example/templates/posts.html +0 -0
- {moosey_cms-0.4.0 → moosey_cms-0.6.0}/src/moosey_cms/__init__.py +0 -0
- {moosey_cms-0.4.0 → moosey_cms-0.6.0}/src/moosey_cms/cache.py +0 -0
- {moosey_cms-0.4.0 → moosey_cms-0.6.0}/src/moosey_cms/file_watcher.py +0 -0
- {moosey_cms-0.4.0 → moosey_cms-0.6.0}/src/moosey_cms/helpers.py +0 -0
- {moosey_cms-0.4.0 → moosey_cms-0.6.0}/src/moosey_cms/md.py +0 -0
- {moosey_cms-0.4.0 → moosey_cms-0.6.0}/src/moosey_cms/models.py +0 -0
- {moosey_cms-0.4.0 → moosey_cms-0.6.0}/src/moosey_cms/seo.py +0 -0
- {moosey_cms-0.4.0 → moosey_cms-0.6.0}/src/moosey_cms/static/js/reload-script.js +0 -0
- {moosey_cms-0.4.0 → moosey_cms-0.6.0}/uv.lock +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: moosey-cms
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.6.0
|
|
4
4
|
Summary: Add your description here
|
|
5
5
|
Requires-Python: >=3.9
|
|
6
6
|
Requires-Dist: cachetools>=6.2.4
|
|
@@ -259,6 +259,8 @@ Moosey CMS comes packed with a comprehensive library of Jinja2 filters to help y
|
|
|
259
259
|
|
|
260
260
|
---
|
|
261
261
|
|
|
262
|
+
[Read More On Filters](docs/filters.md) and how to use some interesting ones such as stripping comments.
|
|
263
|
+
|
|
262
264
|
## ⚙️ Configuration Reference
|
|
263
265
|
|
|
264
266
|
The `init_cms` function accepts the following parameters:
|
|
@@ -242,6 +242,8 @@ Moosey CMS comes packed with a comprehensive library of Jinja2 filters to help y
|
|
|
242
242
|
|
|
243
243
|
---
|
|
244
244
|
|
|
245
|
+
[Read More On Filters](docs/filters.md) and how to use some interesting ones such as stripping comments.
|
|
246
|
+
|
|
245
247
|
## ⚙️ Configuration Reference
|
|
246
248
|
|
|
247
249
|
The `init_cms` function accepts the following parameters:
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
Copyright (c) 2026 Anthony Mugendi
|
|
3
|
+
|
|
4
|
+
This software is released under the MIT License.
|
|
5
|
+
https://opensource.org/licenses/MIT
|
|
6
|
+
-->
|
|
7
|
+
|
|
8
|
+
# Template Filters
|
|
9
|
+
|
|
10
|
+
Moosey CMS comes equipped with a powerful suite of Jinja2 filters. These allow you to format data, manipulate text, and clean up HTML directly within your Markdown files or HTML templates.
|
|
11
|
+
|
|
12
|
+
## Usage
|
|
13
|
+
|
|
14
|
+
Filters are applied using the pipe symbol (`|`). You can chain multiple filters together.
|
|
15
|
+
|
|
16
|
+
```jinja
|
|
17
|
+
{{ variable | filter_name }}
|
|
18
|
+
{{ variable | filter1 | filter2 }}
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## 🧹 HTML & Structure
|
|
24
|
+
|
|
25
|
+
### `strip_comments`
|
|
26
|
+
**Type:** Block Filter
|
|
27
|
+
Removes HTML comments (`<!-- ... -->`) from the enclosed content. This is useful for keeping production code clean while leaving comments in for development.
|
|
28
|
+
|
|
29
|
+
**Arguments:**
|
|
30
|
+
* `enabled` (bool): If `False`, comments are preserved. Default is `True`.
|
|
31
|
+
|
|
32
|
+
**Usage:**
|
|
33
|
+
You typically wrap your entire `base.html` layout with this.
|
|
34
|
+
|
|
35
|
+
```jinja
|
|
36
|
+
<!-- example/templates/layout/base.html -->
|
|
37
|
+
|
|
38
|
+
<!-- Only strip comments if not in development mode -->
|
|
39
|
+
{% filter strip_comments(enabled=(mode != 'development')) %}
|
|
40
|
+
<!DOCTYPE html>
|
|
41
|
+
<html>
|
|
42
|
+
<head>
|
|
43
|
+
<!-- This comment will vanish in production -->
|
|
44
|
+
<title>{{ title }}</title>
|
|
45
|
+
</head>
|
|
46
|
+
<body>
|
|
47
|
+
{{ content }}
|
|
48
|
+
</body>
|
|
49
|
+
</html>
|
|
50
|
+
{% endfilter %}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### `minify_html`
|
|
54
|
+
**Type:** Block Filter
|
|
55
|
+
Reduces file size by removing newlines, tabs, and extra spaces. It collapses multiple spaces into one and removes whitespace between HTML tags.
|
|
56
|
+
|
|
57
|
+
**Arguments:**
|
|
58
|
+
* `enabled` (bool): Default `True`.
|
|
59
|
+
|
|
60
|
+
**⚠️ Important Note:**
|
|
61
|
+
This filter is "aggressive." It does not detect `<pre>` or `<textarea>` tags. If you use code blocks where indentation must be preserved exactly, consider disabling this filter or handling those blocks separately.
|
|
62
|
+
|
|
63
|
+
**Usage Example:**
|
|
64
|
+
|
|
65
|
+
```jinja
|
|
66
|
+
{% minify_html(enabled=(mode != 'development')) %}
|
|
67
|
+
<html>
|
|
68
|
+
...
|
|
69
|
+
</html>
|
|
70
|
+
{% endfilter %}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
**Combined Usage Example:**
|
|
74
|
+
|
|
75
|
+
This is the recommended setup for your `base.html` file to ensure maximum performance in production while keeping development easy.
|
|
76
|
+
|
|
77
|
+
```jinja
|
|
78
|
+
{% filter strip_comments(enabled=(mode != 'development')) | minify_html(enabled=(mode != 'development')) %}
|
|
79
|
+
<html>
|
|
80
|
+
...
|
|
81
|
+
</html>
|
|
82
|
+
{% endfilter %}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## 📅 Date & Time
|
|
88
|
+
|
|
89
|
+
Assuming `date_obj` is a Python datetime object (e.g., from `date: 2026-01-21` in frontmatter).
|
|
90
|
+
|
|
91
|
+
| Filter | Description | Example Input | Output |
|
|
92
|
+
| :--- | :--- | :--- | :--- |
|
|
93
|
+
| **`fancy_date`** | Formats date with ordinal suffix. | `2026-01-21 18:00` | 21st Jan, 2026 at 6:00 PM |
|
|
94
|
+
| **`short_date`** | Standard clean date format. | `2026-01-21` | Jan 21, 2026 |
|
|
95
|
+
| **`iso_date`** | ISO 8601 format (good for meta tags). | `2026-01-21` | 2026-01-21 |
|
|
96
|
+
| **`time_only`** | Extracts just the time. | `2026-01-21 18:00` | 6:00 PM |
|
|
97
|
+
| **`relative_time`** | Human readable time difference. | `(Now - 2 hours)` | 2 hours ago |
|
|
98
|
+
|
|
99
|
+
**Usage:**
|
|
100
|
+
```jinja
|
|
101
|
+
<time>{{ date.created | fancy_date }}</time>
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## 📝 Text Manipulation
|
|
107
|
+
|
|
108
|
+
| Filter | Description | Example Input | Output |
|
|
109
|
+
| :--- | :--- | :--- | :--- |
|
|
110
|
+
| **`truncate_words`** | Cuts text after N words. | `{{ "one two three four" | truncate_words(2) }}` | one two... |
|
|
111
|
+
| **`excerpt`** | Smart truncation that tries to break at the end of a sentence. | *Long paragraph* | *First few sentences...* |
|
|
112
|
+
| **`title_case`** | Capitalizes words intelligently (skips "and", "the", etc). | `a tale of two cities` | A Tale of Two Cities |
|
|
113
|
+
| **`slugify`** | Converts text to URL-friendly format. | `Hello World!` | `hello-world` |
|
|
114
|
+
| **`smart_quotes`** | Converts straight quotes to curly quotes. | `"Hello"` | “Hello” |
|
|
115
|
+
| **`read_time`** | Calculates reading time (approx 200 wpm). | *500 words text* | 3 min read |
|
|
116
|
+
|
|
117
|
+
**Usage:**
|
|
118
|
+
```jinja
|
|
119
|
+
<h1>{{ title | title_case }}</h1>
|
|
120
|
+
<p>{{ content | excerpt(150) }}</p>
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## 💰 Currency & Finance
|
|
126
|
+
|
|
127
|
+
| Filter | Description | Arguments | Output |
|
|
128
|
+
| :--- | :--- | :--- | :--- |
|
|
129
|
+
| **`currency`** | Formats number with symbol. | `code` (default 'USD') | `$1,234.56` |
|
|
130
|
+
| **`compact_currency`** | Shortens large numbers. | `code` (default 'USD') | `$1.5M`, `$45K` |
|
|
131
|
+
| **`currency_name`** | Converts ISO code to name. | - | `KES` → `Kenyan Shilling` |
|
|
132
|
+
|
|
133
|
+
**Usage:**
|
|
134
|
+
```jinja
|
|
135
|
+
<!-- Custom Currency -->
|
|
136
|
+
Price: {{ 4500 | currency('EUR') }}
|
|
137
|
+
<!-- Output: €4,500.00 -->
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## 🌍 Geography & Locale
|
|
143
|
+
|
|
144
|
+
Requires valid ISO 3166-1 alpha-2 or alpha-3 codes.
|
|
145
|
+
|
|
146
|
+
| Filter | Description | Example Input | Output |
|
|
147
|
+
| :--- | :--- | :--- | :--- |
|
|
148
|
+
| **`country_flag`** | Converts country code to Emoji flag. | `US` | 🇺🇸 |
|
|
149
|
+
| **`country_name`** | Converts code to full name. | `DE` | Germany |
|
|
150
|
+
| **`language_name`** | Converts language code to name. | `fr` | French |
|
|
151
|
+
|
|
152
|
+
**Usage:**
|
|
153
|
+
```jinja
|
|
154
|
+
<span>Made in {{ 'JP' | country_flag }} {{ 'JP' | country_name }}</span>
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## 🔢 Numbers & Math
|
|
160
|
+
|
|
161
|
+
| Filter | Description | Example Input | Output |
|
|
162
|
+
| :--- | :--- | :--- | :--- |
|
|
163
|
+
| **`number_format`** | Adds thousand separators. | `10000` | `10,000` |
|
|
164
|
+
| **`percentage`** | Formats float as percent. | `50.5` | `50.5%` |
|
|
165
|
+
| **`ordinal`** | Adds ordinal suffix to integer. | `3` | `3rd` |
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## 🛠 Utilities
|
|
170
|
+
|
|
171
|
+
| Filter | Description | Example Input | Output |
|
|
172
|
+
| :--- | :--- | :--- | :--- |
|
|
173
|
+
| **`filesize`** | Bytes to human readable size. | `1048576` | `1.0 MB` |
|
|
174
|
+
| **`yesno`** | Boolean to text. | `True` | `Yes` (or custom) |
|
|
175
|
+
| **`default_if_none`** | Fallback if value is None. | `None` | *(Default string)* |
|
|
176
|
+
|
|
177
|
+
**Usage:**
|
|
178
|
+
```jinja
|
|
179
|
+
<!-- Custom Yes/No labels -->
|
|
180
|
+
Active: {{ is_active | yesno("Online", "Offline") }}
|
|
181
|
+
|
|
182
|
+
<!-- File Size -->
|
|
183
|
+
Download size: {{ 2500000 | filesize }}
|
|
184
|
+
```
|
|
@@ -472,6 +472,43 @@ def read_time(text: str) -> str:
|
|
|
472
472
|
return "1 min read"
|
|
473
473
|
return f"{minutes} min read"
|
|
474
474
|
|
|
475
|
+
|
|
476
|
+
# ============================================================================
|
|
477
|
+
# HTML UTILITIES
|
|
478
|
+
# ============================================================================
|
|
479
|
+
|
|
480
|
+
def strip_comments(text, enabled=True):
|
|
481
|
+
"""
|
|
482
|
+
Removes HTML comments from the output.
|
|
483
|
+
Usage: {% filter strip_comments(enabled=True) %} ... {% endfilter %}
|
|
484
|
+
"""
|
|
485
|
+
if not enabled or not text:
|
|
486
|
+
return text
|
|
487
|
+
|
|
488
|
+
# Regex: Matches <!-- followed by anything (including newlines) until -->
|
|
489
|
+
# The *? ensures it is non-greedy (stops at the first closing tag)
|
|
490
|
+
return re.sub(r'<!--[\s\S]*?-->', '', str(text))
|
|
491
|
+
|
|
492
|
+
def minify_html(text, enabled=True):
|
|
493
|
+
"""
|
|
494
|
+
Minifies HTML by removing unnecessary whitespace and newlines.
|
|
495
|
+
WARNING: This is a regex-based minifier. It does not respect <pre> tags.
|
|
496
|
+
"""
|
|
497
|
+
if not enabled or not text:
|
|
498
|
+
return text
|
|
499
|
+
|
|
500
|
+
text = str(text)
|
|
501
|
+
|
|
502
|
+
# 1. Normalize whitespace:
|
|
503
|
+
# Replace sequences of whitespace (tabs, newlines) with a single space
|
|
504
|
+
text = re.sub(r'\s+', ' ', text)
|
|
505
|
+
|
|
506
|
+
# 2. Remove space between tags:
|
|
507
|
+
# Turns "</div> <div..." into "</div><div..."
|
|
508
|
+
text = re.sub(r'>\s+<', '><', text)
|
|
509
|
+
|
|
510
|
+
return text.strip()
|
|
511
|
+
|
|
475
512
|
# ============================================================================
|
|
476
513
|
# REGISTRATION FUNCTION
|
|
477
514
|
# ============================================================================
|
|
@@ -511,7 +548,9 @@ def register_filters(jinja_env):
|
|
|
511
548
|
'filesize': filesize,
|
|
512
549
|
'default_if_none': default_if_none,
|
|
513
550
|
'yesno': yesno,
|
|
514
|
-
'read_time':read_time
|
|
551
|
+
'read_time':read_time,
|
|
552
|
+
'strip_comments': strip_comments,
|
|
553
|
+
'minify_html': minify_html
|
|
515
554
|
}
|
|
516
555
|
|
|
517
556
|
for name, func in filters_dict.items():
|
|
@@ -17,11 +17,13 @@ class ScriptInjectorMiddleware(BaseHTTPMiddleware):
|
|
|
17
17
|
self.script = script
|
|
18
18
|
|
|
19
19
|
async def dispatch(self, request: Request, call_next):
|
|
20
|
+
|
|
20
21
|
# Process the request and get the response
|
|
21
22
|
response = await call_next(request)
|
|
22
23
|
|
|
23
24
|
# We only want to touch HTML pages, not JSON APIs or Images
|
|
24
25
|
content_type = response.headers.get("content-type", "")
|
|
26
|
+
|
|
25
27
|
# get content length
|
|
26
28
|
content_length = response.headers.get("content-length")
|
|
27
29
|
|
|
@@ -29,11 +31,10 @@ class ScriptInjectorMiddleware(BaseHTTPMiddleware):
|
|
|
29
31
|
if "text/html" not in content_type:
|
|
30
32
|
return response
|
|
31
33
|
|
|
32
|
-
# Skip if too big (e.g. >
|
|
33
|
-
if content_length and int(content_length) >
|
|
34
|
+
# Skip if too big (e.g. > 10mb) to prevent Memory DoS
|
|
35
|
+
if content_length and int(content_length) > 10 * 1024 * 1024 :
|
|
34
36
|
return response
|
|
35
37
|
|
|
36
|
-
|
|
37
38
|
# Read the response body
|
|
38
39
|
# Note: Response body is a stream, we must consume it to modify it
|
|
39
40
|
response_body = [section async for section in response.body_iterator]
|
|
@@ -51,6 +52,7 @@ class ScriptInjectorMiddleware(BaseHTTPMiddleware):
|
|
|
51
52
|
# Fallback: Just append if no body tag found
|
|
52
53
|
full_body += injection
|
|
53
54
|
|
|
55
|
+
|
|
54
56
|
# Create a NEW Response object
|
|
55
57
|
# We cannot modify the existing response easily because Content-Length
|
|
56
58
|
# would be wrong. Creating a new one recalculates headers.
|
|
@@ -69,6 +71,7 @@ class ScriptInjectorMiddleware(BaseHTTPMiddleware):
|
|
|
69
71
|
|
|
70
72
|
|
|
71
73
|
def inject_script_middleware(app, host, port):
|
|
74
|
+
# print('>>>>>>IIIIII')
|
|
72
75
|
# Your custom script to inject
|
|
73
76
|
package_root = Path(__file__).resolve().parent
|
|
74
77
|
javascript_file = package_root / "static" / "js" / "reload-script.js"
|
|
@@ -85,6 +88,8 @@ def inject_script_middleware(app, host, port):
|
|
|
85
88
|
f"{host}:{port}",
|
|
86
89
|
)
|
|
87
90
|
|
|
91
|
+
# print('RELOAD ', script_data)
|
|
92
|
+
|
|
88
93
|
# Add the middleware
|
|
89
94
|
app.add_middleware(
|
|
90
95
|
ScriptInjectorMiddleware, script=f"<script>{script_data}</script>"
|
|
@@ -24,6 +24,30 @@ from .hot_reload_script import inject_script_middleware
|
|
|
24
24
|
|
|
25
25
|
from fastapi import WebSocket, WebSocketDisconnect
|
|
26
26
|
|
|
27
|
+
from jinja2 import Environment, FileSystemLoader
|
|
28
|
+
from jinja2.ext import Extension
|
|
29
|
+
import re
|
|
30
|
+
|
|
31
|
+
class AutoRemoveCommentsExtension(Extension):
|
|
32
|
+
"""Automatically removes HTML comments from all included files"""
|
|
33
|
+
|
|
34
|
+
def __init__(self, environment):
|
|
35
|
+
super().__init__(environment)
|
|
36
|
+
|
|
37
|
+
# Store original include function
|
|
38
|
+
original_include = environment.globals['include']
|
|
39
|
+
|
|
40
|
+
# Create wrapper that removes comments
|
|
41
|
+
def include_no_comments(template_name, **kwargs):
|
|
42
|
+
# Get the included template
|
|
43
|
+
included = environment.get_template(template_name)
|
|
44
|
+
rendered = included.render(**kwargs)
|
|
45
|
+
# Remove comments
|
|
46
|
+
return re.sub(r'<!--.*?-->', '', rendered, flags=re.DOTALL)
|
|
47
|
+
|
|
48
|
+
# Replace include function
|
|
49
|
+
environment.globals['include_no_comments'] = include_no_comments
|
|
50
|
+
|
|
27
51
|
|
|
28
52
|
class ConnectionManager:
|
|
29
53
|
def __init__(self):
|
|
@@ -81,6 +105,7 @@ def init_cms(
|
|
|
81
105
|
# This ensures site_data is available in 404.html and base.html automatically
|
|
82
106
|
templates.env.globals["site_data"] = site_data
|
|
83
107
|
templates.env.globals["mode"] = mode
|
|
108
|
+
|
|
84
109
|
|
|
85
110
|
# Register all custom filters once
|
|
86
111
|
filters.register_filters(templates.env)
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
3.12
|
|
File without changes
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
[project]
|
|
2
|
-
name = "moosey-cms"
|
|
3
|
-
version = "0.1.0"
|
|
4
|
-
description = "A drop-in Markdown CMS for FastAPI with Hot Reloading"
|
|
5
|
-
readme = "README.md"
|
|
6
|
-
requires-python = ">=3.12"
|
|
7
|
-
dependencies = [
|
|
8
|
-
"cachetools>=6.2.4",
|
|
9
|
-
"inflection>=0.5.1",
|
|
10
|
-
"jinja2>=3.1.6",
|
|
11
|
-
"markdown>=3.10",
|
|
12
|
-
"pymdown-extensions>=10.20",
|
|
13
|
-
"python-frontmatter>=1.1.0",
|
|
14
|
-
"python-slugify>=8.0.4",
|
|
15
|
-
"slugify>=0.0.1",
|
|
16
|
-
]
|
|
17
|
-
|
|
18
|
-
[build-system]
|
|
19
|
-
requires = ["hatchling"]
|
|
20
|
-
build-backend = "hatchling.build"
|
|
21
|
-
|
|
22
|
-
# --- CRITICAL: INCLUDE STATIC FILES ---
|
|
23
|
-
[tool.hatch.build.targets.wheel]
|
|
24
|
-
packages = ["src/moosey_cms"]
|
|
25
|
-
|
|
26
|
-
# This forces the inclusion of non-python files inside the package
|
|
27
|
-
[tool.hatch.build.targets.wheel.force-include]
|
|
28
|
-
"src/simple_cms/static" = "moosey_cms/static"
|
|
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
|
|
File without changes
|
|
File without changes
|