ryland 0.1.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.
- ryland-0.1.0/PKG-INFO +93 -0
- ryland-0.1.0/README.md +80 -0
- ryland-0.1.0/pyproject.toml +24 -0
- ryland-0.1.0/src/ryland/__init__.py +1 -0
- ryland-0.1.0/src/ryland/core.py +60 -0
- ryland-0.1.0/src/ryland/py.typed +0 -0
ryland-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ryland
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A simple static site generation library
|
|
5
|
+
Author: James Tauber
|
|
6
|
+
Author-email: James Tauber <jtauber@jtauber.com>
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
Requires-Dist: jinja2>=3.1.6
|
|
9
|
+
Requires-Dist: markdown>=3.8.2
|
|
10
|
+
Requires-Dist: pyyaml>=6.0.2
|
|
11
|
+
Requires-Python: >=3.12
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
|
|
14
|
+
# Ryland
|
|
15
|
+
|
|
16
|
+
A simple static site generation library
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
## Current Features
|
|
20
|
+
|
|
21
|
+
- Jinja2 templates and a basic markdown filter
|
|
22
|
+
- copying static files and directory trees (for stylesheets, scripts, fonts, images)
|
|
23
|
+
- cache-busting with hashes
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
## History
|
|
27
|
+
|
|
28
|
+
I've generally found most static site generation libraries to either be far too complex for my needs or be too restricted to just blogs so, over the years, I've generated many static sites with lightweight, bespoke Python code and hosted them on GitHub pages. However, I've ended up repeating myself a lot so I'm now cleaning it all up and generalizing my prior work as this library.
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
## Example Usage
|
|
32
|
+
|
|
33
|
+
For now, clone this repo and use as an editable requirement.
|
|
34
|
+
|
|
35
|
+
Write a build script of the following form:
|
|
36
|
+
|
|
37
|
+
```python
|
|
38
|
+
from ryland import Ryland
|
|
39
|
+
|
|
40
|
+
ROOT_DIR = Path(__file__).parent.parent
|
|
41
|
+
DIST_DIR = ROOT_DIR / "dist"
|
|
42
|
+
PANTRY_DIR = ROOT_DIR / "pantry"
|
|
43
|
+
TEMPLATE_DIR = ROOT_DIR / "templates"
|
|
44
|
+
|
|
45
|
+
ryland = Ryland(dist_dir=DIST_DIR, template_dir=TEMPLATE_DIR)
|
|
46
|
+
|
|
47
|
+
ryland.clear_dist()
|
|
48
|
+
ryland.copy_to_dist(PANTRY_DIR / "style.css")
|
|
49
|
+
ryland.calc_hash("style.css")
|
|
50
|
+
|
|
51
|
+
ryland.render_template("404.html", "404.html")
|
|
52
|
+
ryland.render_template("about_us.html", "about-us/index.html")
|
|
53
|
+
|
|
54
|
+
# construct context variables
|
|
55
|
+
|
|
56
|
+
ryland.render_template("homepage.html", "index.html", {
|
|
57
|
+
# context variables
|
|
58
|
+
})
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Cache-Busting Hashes
|
|
62
|
+
|
|
63
|
+
The `calc_hash` makes it possible to do
|
|
64
|
+
|
|
65
|
+
```html
|
|
66
|
+
<link rel="stylesheet" href="/style.css?{{ HASHES['style.css'] }}">
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
in the templates.
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
## Markdown Filter
|
|
73
|
+
|
|
74
|
+
To render a markdown context variable:
|
|
75
|
+
|
|
76
|
+
```
|
|
77
|
+
{{ content | markdown }}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Sites Currently Using Ryland
|
|
81
|
+
|
|
82
|
+
- <https://projectamaze.com>
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
## Roadmap
|
|
86
|
+
|
|
87
|
+
- move over other sites to use Ryland
|
|
88
|
+
- incorporate more common elements that emerge
|
|
89
|
+
- produce a Ryland-generated website for Ryland
|
|
90
|
+
- document how to automatically build with GitHub actions
|
|
91
|
+
- write up a cookbook
|
|
92
|
+
- add a command-line too for starting a Ryland-based site
|
|
93
|
+
|
ryland-0.1.0/README.md
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# Ryland
|
|
2
|
+
|
|
3
|
+
A simple static site generation library
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
## Current Features
|
|
7
|
+
|
|
8
|
+
- Jinja2 templates and a basic markdown filter
|
|
9
|
+
- copying static files and directory trees (for stylesheets, scripts, fonts, images)
|
|
10
|
+
- cache-busting with hashes
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
## History
|
|
14
|
+
|
|
15
|
+
I've generally found most static site generation libraries to either be far too complex for my needs or be too restricted to just blogs so, over the years, I've generated many static sites with lightweight, bespoke Python code and hosted them on GitHub pages. However, I've ended up repeating myself a lot so I'm now cleaning it all up and generalizing my prior work as this library.
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
## Example Usage
|
|
19
|
+
|
|
20
|
+
For now, clone this repo and use as an editable requirement.
|
|
21
|
+
|
|
22
|
+
Write a build script of the following form:
|
|
23
|
+
|
|
24
|
+
```python
|
|
25
|
+
from ryland import Ryland
|
|
26
|
+
|
|
27
|
+
ROOT_DIR = Path(__file__).parent.parent
|
|
28
|
+
DIST_DIR = ROOT_DIR / "dist"
|
|
29
|
+
PANTRY_DIR = ROOT_DIR / "pantry"
|
|
30
|
+
TEMPLATE_DIR = ROOT_DIR / "templates"
|
|
31
|
+
|
|
32
|
+
ryland = Ryland(dist_dir=DIST_DIR, template_dir=TEMPLATE_DIR)
|
|
33
|
+
|
|
34
|
+
ryland.clear_dist()
|
|
35
|
+
ryland.copy_to_dist(PANTRY_DIR / "style.css")
|
|
36
|
+
ryland.calc_hash("style.css")
|
|
37
|
+
|
|
38
|
+
ryland.render_template("404.html", "404.html")
|
|
39
|
+
ryland.render_template("about_us.html", "about-us/index.html")
|
|
40
|
+
|
|
41
|
+
# construct context variables
|
|
42
|
+
|
|
43
|
+
ryland.render_template("homepage.html", "index.html", {
|
|
44
|
+
# context variables
|
|
45
|
+
})
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Cache-Busting Hashes
|
|
49
|
+
|
|
50
|
+
The `calc_hash` makes it possible to do
|
|
51
|
+
|
|
52
|
+
```html
|
|
53
|
+
<link rel="stylesheet" href="/style.css?{{ HASHES['style.css'] }}">
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
in the templates.
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
## Markdown Filter
|
|
60
|
+
|
|
61
|
+
To render a markdown context variable:
|
|
62
|
+
|
|
63
|
+
```
|
|
64
|
+
{{ content | markdown }}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Sites Currently Using Ryland
|
|
68
|
+
|
|
69
|
+
- <https://projectamaze.com>
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
## Roadmap
|
|
73
|
+
|
|
74
|
+
- move over other sites to use Ryland
|
|
75
|
+
- incorporate more common elements that emerge
|
|
76
|
+
- produce a Ryland-generated website for Ryland
|
|
77
|
+
- document how to automatically build with GitHub actions
|
|
78
|
+
- write up a cookbook
|
|
79
|
+
- add a command-line too for starting a Ryland-based site
|
|
80
|
+
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "ryland"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "A simple static site generation library"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
license = "MIT"
|
|
7
|
+
authors = [
|
|
8
|
+
{ name = "James Tauber", email = "jtauber@jtauber.com" }
|
|
9
|
+
]
|
|
10
|
+
requires-python = ">=3.12"
|
|
11
|
+
dependencies = [
|
|
12
|
+
"jinja2>=3.1.6",
|
|
13
|
+
"markdown>=3.8.2",
|
|
14
|
+
"pyyaml>=6.0.2",
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
[build-system]
|
|
18
|
+
requires = ["uv_build>=0.8.14,<0.9.0"]
|
|
19
|
+
build-backend = "uv_build"
|
|
20
|
+
|
|
21
|
+
[dependency-groups]
|
|
22
|
+
dev = [
|
|
23
|
+
"ruff>=0.12.11",
|
|
24
|
+
]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .core import *
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
from hashlib import md5
|
|
2
|
+
from os import makedirs
|
|
3
|
+
from shutil import copy, copytree, rmtree
|
|
4
|
+
|
|
5
|
+
import jinja2
|
|
6
|
+
import markdown
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class Ryland:
|
|
10
|
+
def __init__(self, dist_dir, template_dir):
|
|
11
|
+
self.dist_dir = dist_dir
|
|
12
|
+
self.template_dir = template_dir
|
|
13
|
+
self.hashes = {}
|
|
14
|
+
|
|
15
|
+
self.jinja_env = jinja2.Environment(
|
|
16
|
+
loader=jinja2.FileSystemLoader(template_dir)
|
|
17
|
+
)
|
|
18
|
+
self.jinja_env.filters["markdown"] = markdown_filter
|
|
19
|
+
|
|
20
|
+
def clear_dist(self):
|
|
21
|
+
for child in self.dist_dir.iterdir():
|
|
22
|
+
if child.is_dir():
|
|
23
|
+
rmtree(child)
|
|
24
|
+
else:
|
|
25
|
+
child.unlink()
|
|
26
|
+
|
|
27
|
+
def copy_to_dist(self, source):
|
|
28
|
+
if source.is_dir():
|
|
29
|
+
dest = self.dist_dir / source.name
|
|
30
|
+
copytree(source, dest, dirs_exist_ok=True)
|
|
31
|
+
else:
|
|
32
|
+
copy(source, self.dist_dir / source.name)
|
|
33
|
+
|
|
34
|
+
def calc_hash(self, filename):
|
|
35
|
+
self.hashes[filename] = make_hash(self.dist_dir / filename)
|
|
36
|
+
|
|
37
|
+
def render_template(self, template_name, output_filename, context=None):
|
|
38
|
+
context = context or {}
|
|
39
|
+
template = self.jinja_env.get_template(template_name)
|
|
40
|
+
output_path = self.dist_dir / output_filename
|
|
41
|
+
makedirs(output_path.parent, exist_ok=True)
|
|
42
|
+
with open(output_path, "w") as f:
|
|
43
|
+
f.write(
|
|
44
|
+
template.render(
|
|
45
|
+
{
|
|
46
|
+
"HASHES": self.hashes,
|
|
47
|
+
**context,
|
|
48
|
+
}
|
|
49
|
+
)
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def make_hash(path):
|
|
54
|
+
hasher = md5()
|
|
55
|
+
hasher.update(path.read_bytes())
|
|
56
|
+
return hasher.hexdigest()
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def markdown_filter(text):
|
|
60
|
+
return markdown.markdown(text, extensions=["fenced_code", "codehilite", "tables"])
|
|
File without changes
|