moosey-cms 0.2.0__tar.gz → 0.4.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.2.0 → moosey_cms-0.4.0}/PKG-INFO +1 -2
- {moosey_cms-0.2.0 → moosey_cms-0.4.0}/README.md +0 -1
- {moosey_cms-0.2.0 → moosey_cms-0.4.0}/pyproject.toml +1 -1
- {moosey_cms-0.2.0 → moosey_cms-0.4.0}/src/moosey_cms/file_watcher.py +2 -2
- {moosey_cms-0.2.0 → moosey_cms-0.4.0}/src/moosey_cms/helpers.py +29 -6
- {moosey_cms-0.2.0 → moosey_cms-0.4.0}/src/moosey_cms/main.py +5 -8
- {moosey_cms-0.2.0 → moosey_cms-0.4.0}/src/moosey_cms/models.py +1 -7
- {moosey_cms-0.2.0 → moosey_cms-0.4.0}/src/moosey_cms/seo.py +0 -2
- {moosey_cms-0.2.0 → moosey_cms-0.4.0}/.gitignore +0 -0
- {moosey_cms-0.2.0 → moosey_cms-0.4.0}/.python-version +0 -0
- {moosey_cms-0.2.0 → moosey_cms-0.4.0}/example/assets/example-1.jpeg +0 -0
- {moosey_cms-0.2.0 → moosey_cms-0.4.0}/example/assets/example-2.jpeg +0 -0
- {moosey_cms-0.2.0 → moosey_cms-0.4.0}/example/content/about.md +0 -0
- {moosey_cms-0.2.0 → moosey_cms-0.4.0}/example/content/index.md +0 -0
- {moosey_cms-0.2.0 → moosey_cms-0.4.0}/example/content/pages/features.md +0 -0
- {moosey_cms-0.2.0 → moosey_cms-0.4.0}/example/content/posts/building-modern-apps.md +0 -0
- {moosey_cms-0.2.0 → moosey_cms-0.4.0}/example/content/posts/index.md +0 -0
- {moosey_cms-0.2.0 → moosey_cms-0.4.0}/example/main.py +0 -0
- {moosey_cms-0.2.0 → moosey_cms-0.4.0}/example/templates/404.html +0 -0
- {moosey_cms-0.2.0 → moosey_cms-0.4.0}/example/templates/components/sidebar.html +0 -0
- {moosey_cms-0.2.0 → moosey_cms-0.4.0}/example/templates/index.html +0 -0
- {moosey_cms-0.2.0 → moosey_cms-0.4.0}/example/templates/layout/base.html +0 -0
- {moosey_cms-0.2.0 → moosey_cms-0.4.0}/example/templates/page.html +0 -0
- {moosey_cms-0.2.0 → moosey_cms-0.4.0}/example/templates/post.html +0 -0
- {moosey_cms-0.2.0 → moosey_cms-0.4.0}/example/templates/posts.html +0 -0
- {moosey_cms-0.2.0 → moosey_cms-0.4.0}/src/moosey_cms/.python-version +0 -0
- {moosey_cms-0.2.0 → moosey_cms-0.4.0}/src/moosey_cms/__init__.py +0 -0
- {moosey_cms-0.2.0 → moosey_cms-0.4.0}/src/moosey_cms/cache.py +0 -0
- {moosey_cms-0.2.0 → moosey_cms-0.4.0}/src/moosey_cms/filters.py +0 -0
- {moosey_cms-0.2.0 → moosey_cms-0.4.0}/src/moosey_cms/hot_reload_script.py +0 -0
- {moosey_cms-0.2.0 → moosey_cms-0.4.0}/src/moosey_cms/md.py +0 -0
- {moosey_cms-0.2.0 → moosey_cms-0.4.0}/src/moosey_cms/py.typed +0 -0
- {moosey_cms-0.2.0 → moosey_cms-0.4.0}/src/moosey_cms/pyproject.toml +0 -0
- {moosey_cms-0.2.0 → moosey_cms-0.4.0}/src/moosey_cms/static/js/reload-script.js +0 -0
- {moosey_cms-0.2.0 → moosey_cms-0.4.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.4.0
|
|
4
4
|
Summary: Add your description here
|
|
5
5
|
Requires-Python: >=3.9
|
|
6
6
|
Requires-Dist: cachetools>=6.2.4
|
|
@@ -271,7 +271,6 @@ The `init_cms` function accepts the following parameters:
|
|
|
271
271
|
| `dirs` | `dict` | Dictionary containing `content` and `templates` Paths. |
|
|
272
272
|
| `mode` | `str` | `"development"` (enables hot reload/no cache) or `"production"`. |
|
|
273
273
|
| `site_data` | `dict` | Global data (Name, Author, Social Links). |
|
|
274
|
-
| `site_code` | `dict` | Inject custom HTML (e.g., analytics) via `{{ site_code.footer_code }}`. |
|
|
275
274
|
|
|
276
275
|
---
|
|
277
276
|
|
|
@@ -254,7 +254,6 @@ The `init_cms` function accepts the following parameters:
|
|
|
254
254
|
| `dirs` | `dict` | Dictionary containing `content` and `templates` Paths. |
|
|
255
255
|
| `mode` | `str` | `"development"` (enables hot reload/no cache) or `"production"`. |
|
|
256
256
|
| `site_data` | `dict` | Global data (Name, Author, Social Links). |
|
|
257
|
-
| `site_code` | `dict` | Inject custom HTML (e.g., analytics) via `{{ site_code.footer_code }}`. |
|
|
258
257
|
|
|
259
258
|
---
|
|
260
259
|
|
|
@@ -5,13 +5,13 @@ from watchdog.events import FileSystemEventHandler
|
|
|
5
5
|
class FileChangeHandler(FileSystemEventHandler):
|
|
6
6
|
def __init__(self, callback):
|
|
7
7
|
self.callback = callback
|
|
8
|
-
self.ts =0
|
|
8
|
+
self.ts = 0
|
|
9
9
|
|
|
10
10
|
def on_any_event(self, event):
|
|
11
11
|
if event.is_directory:
|
|
12
12
|
return
|
|
13
13
|
|
|
14
|
-
if event.event_type
|
|
14
|
+
if event.event_type in ["modified", "created", "deleted"]:
|
|
15
15
|
# Trigger the callback
|
|
16
16
|
self.callback(event.src_path, event.event_type)
|
|
17
17
|
|
|
@@ -205,7 +205,7 @@ def get_directory_navigation(
|
|
|
205
205
|
meta_file = entry / 'index.md' if entry.is_dir() else entry
|
|
206
206
|
|
|
207
207
|
# Defaults
|
|
208
|
-
|
|
208
|
+
sort_order = 9999
|
|
209
209
|
display_title = entry.stem.replace("-", " ").title()
|
|
210
210
|
nav_group = None
|
|
211
211
|
external_url = None
|
|
@@ -229,13 +229,13 @@ def get_directory_navigation(
|
|
|
229
229
|
continue
|
|
230
230
|
|
|
231
231
|
# 2. Ordering
|
|
232
|
-
if 'order' in meta:
|
|
232
|
+
if 'order' in meta: sort_order = int(meta['order'])
|
|
233
233
|
|
|
234
234
|
# 3. Titles & Grouping
|
|
235
235
|
if 'nav_title' in meta: display_title = meta['nav_title']
|
|
236
236
|
elif 'title' in meta: display_title = meta['title']
|
|
237
237
|
|
|
238
|
-
nav_group = meta.get('group')
|
|
238
|
+
nav_group = meta.get('group') or ""
|
|
239
239
|
|
|
240
240
|
# 4. External Links
|
|
241
241
|
if 'external_link' in meta:
|
|
@@ -265,13 +265,36 @@ def get_directory_navigation(
|
|
|
265
265
|
"url": entry_url,
|
|
266
266
|
"is_active": is_active,
|
|
267
267
|
"is_dir": entry.is_dir(),
|
|
268
|
-
"
|
|
268
|
+
"order": sort_order,
|
|
269
269
|
"group": nav_group,
|
|
270
270
|
"target": target
|
|
271
271
|
})
|
|
272
272
|
|
|
273
|
-
# Sorting:
|
|
274
|
-
items.sort(key=lambda x: (x['
|
|
273
|
+
# Sorting: order first, then Name
|
|
274
|
+
# items.sort(key=lambda x: (x['order'], x['name']))
|
|
275
|
+
group_min_orders = {}
|
|
276
|
+
|
|
277
|
+
for item in items:
|
|
278
|
+
g = item['group']
|
|
279
|
+
w = item['order']
|
|
280
|
+
# If we haven't seen this group, or if this item is lighter (more important)
|
|
281
|
+
if g not in group_min_orders or w < group_min_orders[g]:
|
|
282
|
+
group_min_orders[g] = w
|
|
283
|
+
|
|
284
|
+
# 2. Sort the list with a Tuple Key
|
|
285
|
+
items.sort(key=lambda x: (
|
|
286
|
+
# Primary: Group order (Groups with important items float to top)
|
|
287
|
+
group_min_orders[x['group']],
|
|
288
|
+
|
|
289
|
+
# Secondary: Group Name (Keep groups clustered together)
|
|
290
|
+
x['group'],
|
|
291
|
+
|
|
292
|
+
# Tertiary: Item order (Sort items inside the group)
|
|
293
|
+
x['order'],
|
|
294
|
+
|
|
295
|
+
# Quaternary: Item Name (Alphabetical fallback)
|
|
296
|
+
x['name']
|
|
297
|
+
))
|
|
275
298
|
|
|
276
299
|
except OSError:
|
|
277
300
|
pass
|
|
@@ -46,7 +46,7 @@ class ConnectionManager:
|
|
|
46
46
|
self.disconnect(connection)
|
|
47
47
|
|
|
48
48
|
|
|
49
|
-
from .models import CMSConfig, Dirs,
|
|
49
|
+
from .models import CMSConfig, Dirs, SiteData
|
|
50
50
|
|
|
51
51
|
|
|
52
52
|
def init_cms(
|
|
@@ -56,7 +56,6 @@ def init_cms(
|
|
|
56
56
|
dirs: Dirs,
|
|
57
57
|
mode: str,
|
|
58
58
|
site_data: SiteData = {},
|
|
59
|
-
site_code: SiteCode = {},
|
|
60
59
|
):
|
|
61
60
|
|
|
62
61
|
# validate dirs inputs
|
|
@@ -65,8 +64,7 @@ def init_cms(
|
|
|
65
64
|
port=port,
|
|
66
65
|
dirs=dirs,
|
|
67
66
|
mode=mode,
|
|
68
|
-
site_data=site_data
|
|
69
|
-
site_code=site_code,
|
|
67
|
+
site_data=site_data
|
|
70
68
|
)
|
|
71
69
|
|
|
72
70
|
# resolve paths
|
|
@@ -77,13 +75,11 @@ def init_cms(
|
|
|
77
75
|
templates = Jinja2Templates(directory=str(dirs["templates"]), extensions=[])
|
|
78
76
|
|
|
79
77
|
# Important for filters like seo to access them
|
|
80
|
-
app.state.site_code = site_code
|
|
81
78
|
app.state.site_data = site_data
|
|
82
79
|
app.state.mode = mode
|
|
83
80
|
|
|
84
81
|
# This ensures site_data is available in 404.html and base.html automatically
|
|
85
82
|
templates.env.globals["site_data"] = site_data
|
|
86
|
-
templates.env.globals["site_code"] = site_code
|
|
87
83
|
templates.env.globals["mode"] = mode
|
|
88
84
|
|
|
89
85
|
# Register all custom filters once
|
|
@@ -221,8 +217,7 @@ def init_routes(app, dirs: Dirs, templates, mode, reloader):
|
|
|
221
217
|
template_data = {
|
|
222
218
|
**template_data,
|
|
223
219
|
**front_matter,
|
|
224
|
-
"site_data": app.state.site_data
|
|
225
|
-
"site_code": app.state.site_code,
|
|
220
|
+
"site_data": app.state.site_data
|
|
226
221
|
}
|
|
227
222
|
|
|
228
223
|
# Render jinja inside frontmatter strings
|
|
@@ -264,6 +259,8 @@ def init_routes(app, dirs: Dirs, templates, mode, reloader):
|
|
|
264
259
|
|
|
265
260
|
template_data = {**template_data, **md_data}
|
|
266
261
|
|
|
262
|
+
# pprint(nav_items)
|
|
263
|
+
|
|
267
264
|
# 8. Render
|
|
268
265
|
return templates.TemplateResponse(
|
|
269
266
|
template_name,
|
|
@@ -44,12 +44,6 @@ class SiteData(BaseModel):
|
|
|
44
44
|
social: Optional[SocialConfig] = Field(..., description="Social media links")
|
|
45
45
|
|
|
46
46
|
|
|
47
|
-
class SiteCode(BaseModel):
|
|
48
|
-
"""Custom HTML/code snippets for the site"""
|
|
49
|
-
styled_name: Optional[str] = Field(None, description="Styled HTML name")
|
|
50
|
-
header_code: Optional[str] = Field(None, description="Code to inject in header")
|
|
51
|
-
footer_code: Optional[str] = Field(None, description="Code to inject in footer")
|
|
52
|
-
|
|
53
47
|
|
|
54
48
|
class Dirs(BaseModel):
|
|
55
49
|
"""Directory paths configuration"""
|
|
@@ -76,4 +70,4 @@ class CMSConfig(BaseModel):
|
|
|
76
70
|
description="Application mode"
|
|
77
71
|
)
|
|
78
72
|
site_data: Optional[SiteData] = Field(..., description="Site metadata")
|
|
79
|
-
site_code: Optional[SiteCode] = Field(..., description="Custom site code")
|
|
73
|
+
# site_code: Optional[SiteCode] = Field(..., description="Custom site code")
|
|
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
|
|
File without changes
|