stapler-ssg 0.1.2__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.
- stapler_ssg-0.1.2/.github/workflows/publish.yml +24 -0
- stapler_ssg-0.1.2/.gitignore +2 -0
- stapler_ssg-0.1.2/Bakefile +13 -0
- stapler_ssg-0.1.2/LICENSE +24 -0
- stapler_ssg-0.1.2/PKG-INFO +284 -0
- stapler_ssg-0.1.2/README.md +264 -0
- stapler_ssg-0.1.2/example_site/.gitignore +2 -0
- stapler_ssg-0.1.2/example_site/site/about.html +6 -0
- stapler_ssg-0.1.2/example_site/site/assets/styles/custom.css +25 -0
- stapler_ssg-0.1.2/example_site/site/blog/getting-started.md +26 -0
- stapler_ssg-0.1.2/example_site/site/blog/welcome-to-stapler.md +19 -0
- stapler_ssg-0.1.2/example_site/site/index.html +6 -0
- stapler_ssg-0.1.2/example_site/site/templates/base.html +24 -0
- stapler_ssg-0.1.2/example_site/site/templates/blog_index.html +11 -0
- stapler_ssg-0.1.2/example_site/site/templates/blog_post.html +9 -0
- stapler_ssg-0.1.2/example_site/stapler.toml +11 -0
- stapler_ssg-0.1.2/pyproject.toml +42 -0
- stapler_ssg-0.1.2/requirements.txt +6 -0
- stapler_ssg-0.1.2/stapler/__init__.py +1 -0
- stapler_ssg-0.1.2/stapler/cli.py +72 -0
- stapler_ssg-0.1.2/stapler/config.py +122 -0
- stapler_ssg-0.1.2/stapler/core/__init__.py +0 -0
- stapler_ssg-0.1.2/stapler/core/engine.py +184 -0
- stapler_ssg-0.1.2/stapler/core/utils.py +83 -0
- stapler_ssg-0.1.2/stapler/plugins/__init__.py +0 -0
- stapler_ssg-0.1.2/stapler/plugins/blog.py +162 -0
- stapler_ssg-0.1.2/stapler/plugins/sitemap.py +55 -0
- stapler_ssg-0.1.2/stapler/server.py +139 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
publish:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
permissions:
|
|
11
|
+
id-token: write
|
|
12
|
+
|
|
13
|
+
steps:
|
|
14
|
+
- uses: actions/checkout@v4
|
|
15
|
+
|
|
16
|
+
- uses: actions/setup-python@v5
|
|
17
|
+
with:
|
|
18
|
+
python-version: "3.11"
|
|
19
|
+
|
|
20
|
+
- run: pip install build
|
|
21
|
+
|
|
22
|
+
- run: python -m build
|
|
23
|
+
|
|
24
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
This is free and unencumbered software released into the public domain.
|
|
2
|
+
|
|
3
|
+
Anyone is free to copy, modify, publish, use, compile, sell, or
|
|
4
|
+
distribute this software, either in source code form or as a compiled
|
|
5
|
+
binary, for any purpose, commercial or non-commercial, and by any
|
|
6
|
+
means.
|
|
7
|
+
|
|
8
|
+
In jurisdictions that recognize copyright laws, the author or authors
|
|
9
|
+
of this software dedicate any and all copyright interest in the
|
|
10
|
+
software to the public domain. We make this dedication for the benefit
|
|
11
|
+
of the public at large and to the detriment of our heirs and
|
|
12
|
+
successors. We intend this dedication to be an overt act of
|
|
13
|
+
relinquishment in perpetuity of all present and future rights to this
|
|
14
|
+
software under copyright law.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
19
|
+
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
|
20
|
+
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
|
21
|
+
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
22
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
|
23
|
+
|
|
24
|
+
For more information, please refer to <https://unlicense.org>
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: stapler-ssg
|
|
3
|
+
Version: 0.1.2
|
|
4
|
+
Summary: Simple Jinja-based static site generator
|
|
5
|
+
Project-URL: Homepage, https://github.com/gijs6/stapler
|
|
6
|
+
Project-URL: Repository, https://github.com/gijs6/stapler
|
|
7
|
+
Author-email: Gijs6 <me@gijs6.nl>
|
|
8
|
+
License: Unlicense
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Requires-Python: >=3.11
|
|
11
|
+
Requires-Dist: colorama>=0.4.6
|
|
12
|
+
Requires-Dist: feedgen>=1.0.0
|
|
13
|
+
Requires-Dist: jinja2>=3.1.0
|
|
14
|
+
Requires-Dist: markdown>=3.5.0
|
|
15
|
+
Requires-Dist: pyyaml>=6.0
|
|
16
|
+
Requires-Dist: watchdog>=3.0.0
|
|
17
|
+
Provides-Extra: dev
|
|
18
|
+
Requires-Dist: ruff>=0.1.0; extra == 'dev'
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
|
|
21
|
+
# Stapler
|
|
22
|
+
|
|
23
|
+
A simple static site generator built with Jinja and Markdown.
|
|
24
|
+
|
|
25
|
+
## Installation
|
|
26
|
+
|
|
27
|
+
Clone the repo:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
git clone https://github.com/gijs6/stapler.git
|
|
31
|
+
cd stapler
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Create a virtual environment (recommended):
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
python -m venv .venv
|
|
38
|
+
source .venv/bin/activate
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Install:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
pip install -e .
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Or with dev dependencies:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
pip install -e ".[dev]"
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Quick start
|
|
54
|
+
|
|
55
|
+
1. Create a `stapler.toml` in your project root:
|
|
56
|
+
|
|
57
|
+
```toml
|
|
58
|
+
[site]
|
|
59
|
+
url = "https://yoursite.com"
|
|
60
|
+
title = "Your site"
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
2. Put your content in a `site/` directory (the default). Templates go in `site/templates/`.
|
|
64
|
+
|
|
65
|
+
3. Run:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
stapler serve # local dev server on port 8000
|
|
69
|
+
stapler build # production build
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Configuration
|
|
73
|
+
|
|
74
|
+
### Required
|
|
75
|
+
|
|
76
|
+
```toml
|
|
77
|
+
[site]
|
|
78
|
+
url = "https://yoursite.com"
|
|
79
|
+
title = "Your site"
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Optional
|
|
83
|
+
|
|
84
|
+
#### Site metadata
|
|
85
|
+
|
|
86
|
+
```toml
|
|
87
|
+
[site]
|
|
88
|
+
description = "About your site"
|
|
89
|
+
base_path = "/blog" # Deploy to example.com/blog instead of the root
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
#### Author info
|
|
93
|
+
|
|
94
|
+
Used in RSS/Atom feeds.
|
|
95
|
+
|
|
96
|
+
```toml
|
|
97
|
+
[site.author]
|
|
98
|
+
name = "Your name"
|
|
99
|
+
email = "you@example.com"
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
#### Directories
|
|
103
|
+
|
|
104
|
+
All paths are relative to where you run `stapler`.
|
|
105
|
+
|
|
106
|
+
```toml
|
|
107
|
+
[directories]
|
|
108
|
+
site = "site" # Content directory (default: "site")
|
|
109
|
+
build = "build" # Production output (default: "build")
|
|
110
|
+
build_dev = "build-dev" # Dev server output (default: "build-dev")
|
|
111
|
+
templates = "templates" # Templates folder inside the site directory (default: "templates")
|
|
112
|
+
blog = "blog" # Blog posts folder inside the site directory (default: "blog")
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
#### Default template
|
|
116
|
+
|
|
117
|
+
The template used for HTML pages that have front matter but no `template` field.
|
|
118
|
+
|
|
119
|
+
```toml
|
|
120
|
+
[templates]
|
|
121
|
+
default = "base.html"
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
#### Blog
|
|
125
|
+
|
|
126
|
+
```toml
|
|
127
|
+
[features.blog]
|
|
128
|
+
enabled = true # Enable blog functionality (default: false)
|
|
129
|
+
template = "blog_post.html" # Template for individual posts
|
|
130
|
+
index_template = "blog_index.html" # Template for the blog index page
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
#### Sitemap and feeds
|
|
134
|
+
|
|
135
|
+
```toml
|
|
136
|
+
[features]
|
|
137
|
+
sitemap = true # Generate sitemap.xml (default: true)
|
|
138
|
+
|
|
139
|
+
[features.feeds]
|
|
140
|
+
rss = true # Generate rss.xml (default: true)
|
|
141
|
+
atom = true # Generate atom.xml (default: true)
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Feeds are only generated when the blog feature is enabled.
|
|
145
|
+
|
|
146
|
+
#### Markdown extensions
|
|
147
|
+
|
|
148
|
+
```toml
|
|
149
|
+
[markdown]
|
|
150
|
+
extensions = ["meta", "tables", "fenced_code"] # Python-Markdown extensions
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## How it works
|
|
154
|
+
|
|
155
|
+
### Pages
|
|
156
|
+
|
|
157
|
+
Any `.html` or `.md` file in your site directory (excluding the templates and blog folders) becomes a page.
|
|
158
|
+
|
|
159
|
+
#### Markdown files
|
|
160
|
+
|
|
161
|
+
Markdown files are always rendered to HTML. If the front matter includes a `template` field, the result is passed to that template as `page.content`. Without a `template` field (or without front matter entirely), the raw HTML is written directly.
|
|
162
|
+
|
|
163
|
+
```markdown
|
|
164
|
+
---
|
|
165
|
+
template: base.html
|
|
166
|
+
title: My page
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
# Content
|
|
170
|
+
|
|
171
|
+
Regular markdown here
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
#### HTML files
|
|
175
|
+
|
|
176
|
+
HTML files with front matter are rendered through a template. The `template` field in front matter takes precedence; if omitted, the default template from `[templates].default` is used.
|
|
177
|
+
|
|
178
|
+
```html
|
|
179
|
+
---
|
|
180
|
+
title: My page
|
|
181
|
+
---
|
|
182
|
+
<h1>Content here</h1>
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
HTML files without front matter are treated as Jinja templates directly:
|
|
186
|
+
|
|
187
|
+
```html
|
|
188
|
+
{% extends "base.html" %}
|
|
189
|
+
{% block content %}
|
|
190
|
+
<h1>Hello</h1>
|
|
191
|
+
{% endblock %}
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
Front matter is YAML. All fields are available as `page.metadata.<field>` in your templates.
|
|
195
|
+
|
|
196
|
+
#### Static files
|
|
197
|
+
|
|
198
|
+
Anything that's not a `.html` or `.md` file (and not in your templates or blog folder) is copied as-is to the output directory.
|
|
199
|
+
|
|
200
|
+
### Blog
|
|
201
|
+
|
|
202
|
+
Enable the blog feature in your config, then put `.md` files in your blog directory.
|
|
203
|
+
|
|
204
|
+
```markdown
|
|
205
|
+
---
|
|
206
|
+
title: My post
|
|
207
|
+
date: 2025-01-15
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
Post content here
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
The `date` field is optional. If omitted, stapler tries to infer it from the file's git history.
|
|
214
|
+
|
|
215
|
+
### Templates
|
|
216
|
+
|
|
217
|
+
Templates live in the directory you configured (default: `site/templates/`).
|
|
218
|
+
|
|
219
|
+
#### Available in all templates
|
|
220
|
+
|
|
221
|
+
- `data`: build info
|
|
222
|
+
- `data.now`: current build time
|
|
223
|
+
- `data.now.date.long`: date as `%B %d, %Y` (e.g. `April 12, 2026`)
|
|
224
|
+
- `data.now.date.short`: date as `%Y-%m-%d` (e.g. `2026-04-12`)
|
|
225
|
+
- `data.now.time`: time as `%H:%M:%S`
|
|
226
|
+
- `data.now.iso`: datetime as ISO 8601
|
|
227
|
+
- `data.last_commit`: last git commit info (`None` if not in a git repo)
|
|
228
|
+
- `data.last_commit.hash.short`: short 7-character commit hash
|
|
229
|
+
- `data.last_commit.hash.long`: full commit hash
|
|
230
|
+
- `data.last_commit.dt.date.long`: date as `%B %d, %Y` (e.g. `April 12, 2026`)
|
|
231
|
+
- `data.last_commit.dt.date.short`: date as `%Y-%m-%d` (e.g. `2026-04-12`)
|
|
232
|
+
- `data.last_commit.dt.time`: time as `%H:%M:%S`
|
|
233
|
+
- `data.last_commit.dt.iso`: datetime as ISO 8601
|
|
234
|
+
|
|
235
|
+
#### Regular page templates
|
|
236
|
+
|
|
237
|
+
- `page`: the current page
|
|
238
|
+
- `page.active_page`: identifier derived from the filename (e.g. `about` for `about.html`, `home` for `index.html`), useful for highlighting the active nav item
|
|
239
|
+
- `page.canonical_path`: URL path of the page (e.g. `/about`)
|
|
240
|
+
- `page.content`: page content as HTML (only present if the page has front matter)
|
|
241
|
+
- `page.metadata.<field>`: any front matter field (e.g. `page.metadata.title`)
|
|
242
|
+
|
|
243
|
+
#### Blog post template
|
|
244
|
+
|
|
245
|
+
- `page`: navigation info
|
|
246
|
+
- `page.active_page`: name of the blog directory (e.g. `blog`)
|
|
247
|
+
- `page.canonical_path`: URL path of the post (e.g. `/blog/my-post`)
|
|
248
|
+
- `post`: the current blog post
|
|
249
|
+
- `post.title`: post title (from front matter, or derived from the filename)
|
|
250
|
+
- `post.slug`: URL slug (filename without `.md`)
|
|
251
|
+
- `post.content`: post content as HTML
|
|
252
|
+
- `post.date`: date as `%Y-%m-%d` (e.g. `2026-04-12`), only set if a date is available
|
|
253
|
+
- `post.date_iso`: date as ISO 8601, only set if a date is available
|
|
254
|
+
- `data`: same as above
|
|
255
|
+
|
|
256
|
+
#### Blog index template
|
|
257
|
+
|
|
258
|
+
- `page`: navigation info
|
|
259
|
+
- `page.active_page`: name of the blog directory (e.g. `blog`)
|
|
260
|
+
- `page.canonical_path`: URL path of the blog index (e.g. `/blog`)
|
|
261
|
+
- `posts`: list of all blog posts sorted newest first; each item has the same fields as `post` above
|
|
262
|
+
- `data`: same as above
|
|
263
|
+
|
|
264
|
+
## CLI
|
|
265
|
+
|
|
266
|
+
```bash
|
|
267
|
+
# Build with default config (stapler.toml)
|
|
268
|
+
stapler build
|
|
269
|
+
|
|
270
|
+
# Build with custom config
|
|
271
|
+
stapler build -c myconfig.toml
|
|
272
|
+
|
|
273
|
+
# Serve on default port (8000)
|
|
274
|
+
stapler serve
|
|
275
|
+
|
|
276
|
+
# Serve on custom port
|
|
277
|
+
stapler serve -p 3000
|
|
278
|
+
|
|
279
|
+
# Serve with custom config and port
|
|
280
|
+
stapler serve -c myconfig.toml -p 3000
|
|
281
|
+
|
|
282
|
+
# Show version
|
|
283
|
+
stapler --version
|
|
284
|
+
```
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
# Stapler
|
|
2
|
+
|
|
3
|
+
A simple static site generator built with Jinja and Markdown.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
Clone the repo:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
git clone https://github.com/gijs6/stapler.git
|
|
11
|
+
cd stapler
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Create a virtual environment (recommended):
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
python -m venv .venv
|
|
18
|
+
source .venv/bin/activate
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Install:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
pip install -e .
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Or with dev dependencies:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
pip install -e ".[dev]"
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Quick start
|
|
34
|
+
|
|
35
|
+
1. Create a `stapler.toml` in your project root:
|
|
36
|
+
|
|
37
|
+
```toml
|
|
38
|
+
[site]
|
|
39
|
+
url = "https://yoursite.com"
|
|
40
|
+
title = "Your site"
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
2. Put your content in a `site/` directory (the default). Templates go in `site/templates/`.
|
|
44
|
+
|
|
45
|
+
3. Run:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
stapler serve # local dev server on port 8000
|
|
49
|
+
stapler build # production build
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Configuration
|
|
53
|
+
|
|
54
|
+
### Required
|
|
55
|
+
|
|
56
|
+
```toml
|
|
57
|
+
[site]
|
|
58
|
+
url = "https://yoursite.com"
|
|
59
|
+
title = "Your site"
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Optional
|
|
63
|
+
|
|
64
|
+
#### Site metadata
|
|
65
|
+
|
|
66
|
+
```toml
|
|
67
|
+
[site]
|
|
68
|
+
description = "About your site"
|
|
69
|
+
base_path = "/blog" # Deploy to example.com/blog instead of the root
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
#### Author info
|
|
73
|
+
|
|
74
|
+
Used in RSS/Atom feeds.
|
|
75
|
+
|
|
76
|
+
```toml
|
|
77
|
+
[site.author]
|
|
78
|
+
name = "Your name"
|
|
79
|
+
email = "you@example.com"
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
#### Directories
|
|
83
|
+
|
|
84
|
+
All paths are relative to where you run `stapler`.
|
|
85
|
+
|
|
86
|
+
```toml
|
|
87
|
+
[directories]
|
|
88
|
+
site = "site" # Content directory (default: "site")
|
|
89
|
+
build = "build" # Production output (default: "build")
|
|
90
|
+
build_dev = "build-dev" # Dev server output (default: "build-dev")
|
|
91
|
+
templates = "templates" # Templates folder inside the site directory (default: "templates")
|
|
92
|
+
blog = "blog" # Blog posts folder inside the site directory (default: "blog")
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
#### Default template
|
|
96
|
+
|
|
97
|
+
The template used for HTML pages that have front matter but no `template` field.
|
|
98
|
+
|
|
99
|
+
```toml
|
|
100
|
+
[templates]
|
|
101
|
+
default = "base.html"
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
#### Blog
|
|
105
|
+
|
|
106
|
+
```toml
|
|
107
|
+
[features.blog]
|
|
108
|
+
enabled = true # Enable blog functionality (default: false)
|
|
109
|
+
template = "blog_post.html" # Template for individual posts
|
|
110
|
+
index_template = "blog_index.html" # Template for the blog index page
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
#### Sitemap and feeds
|
|
114
|
+
|
|
115
|
+
```toml
|
|
116
|
+
[features]
|
|
117
|
+
sitemap = true # Generate sitemap.xml (default: true)
|
|
118
|
+
|
|
119
|
+
[features.feeds]
|
|
120
|
+
rss = true # Generate rss.xml (default: true)
|
|
121
|
+
atom = true # Generate atom.xml (default: true)
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Feeds are only generated when the blog feature is enabled.
|
|
125
|
+
|
|
126
|
+
#### Markdown extensions
|
|
127
|
+
|
|
128
|
+
```toml
|
|
129
|
+
[markdown]
|
|
130
|
+
extensions = ["meta", "tables", "fenced_code"] # Python-Markdown extensions
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## How it works
|
|
134
|
+
|
|
135
|
+
### Pages
|
|
136
|
+
|
|
137
|
+
Any `.html` or `.md` file in your site directory (excluding the templates and blog folders) becomes a page.
|
|
138
|
+
|
|
139
|
+
#### Markdown files
|
|
140
|
+
|
|
141
|
+
Markdown files are always rendered to HTML. If the front matter includes a `template` field, the result is passed to that template as `page.content`. Without a `template` field (or without front matter entirely), the raw HTML is written directly.
|
|
142
|
+
|
|
143
|
+
```markdown
|
|
144
|
+
---
|
|
145
|
+
template: base.html
|
|
146
|
+
title: My page
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
# Content
|
|
150
|
+
|
|
151
|
+
Regular markdown here
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
#### HTML files
|
|
155
|
+
|
|
156
|
+
HTML files with front matter are rendered through a template. The `template` field in front matter takes precedence; if omitted, the default template from `[templates].default` is used.
|
|
157
|
+
|
|
158
|
+
```html
|
|
159
|
+
---
|
|
160
|
+
title: My page
|
|
161
|
+
---
|
|
162
|
+
<h1>Content here</h1>
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
HTML files without front matter are treated as Jinja templates directly:
|
|
166
|
+
|
|
167
|
+
```html
|
|
168
|
+
{% extends "base.html" %}
|
|
169
|
+
{% block content %}
|
|
170
|
+
<h1>Hello</h1>
|
|
171
|
+
{% endblock %}
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
Front matter is YAML. All fields are available as `page.metadata.<field>` in your templates.
|
|
175
|
+
|
|
176
|
+
#### Static files
|
|
177
|
+
|
|
178
|
+
Anything that's not a `.html` or `.md` file (and not in your templates or blog folder) is copied as-is to the output directory.
|
|
179
|
+
|
|
180
|
+
### Blog
|
|
181
|
+
|
|
182
|
+
Enable the blog feature in your config, then put `.md` files in your blog directory.
|
|
183
|
+
|
|
184
|
+
```markdown
|
|
185
|
+
---
|
|
186
|
+
title: My post
|
|
187
|
+
date: 2025-01-15
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
Post content here
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
The `date` field is optional. If omitted, stapler tries to infer it from the file's git history.
|
|
194
|
+
|
|
195
|
+
### Templates
|
|
196
|
+
|
|
197
|
+
Templates live in the directory you configured (default: `site/templates/`).
|
|
198
|
+
|
|
199
|
+
#### Available in all templates
|
|
200
|
+
|
|
201
|
+
- `data`: build info
|
|
202
|
+
- `data.now`: current build time
|
|
203
|
+
- `data.now.date.long`: date as `%B %d, %Y` (e.g. `April 12, 2026`)
|
|
204
|
+
- `data.now.date.short`: date as `%Y-%m-%d` (e.g. `2026-04-12`)
|
|
205
|
+
- `data.now.time`: time as `%H:%M:%S`
|
|
206
|
+
- `data.now.iso`: datetime as ISO 8601
|
|
207
|
+
- `data.last_commit`: last git commit info (`None` if not in a git repo)
|
|
208
|
+
- `data.last_commit.hash.short`: short 7-character commit hash
|
|
209
|
+
- `data.last_commit.hash.long`: full commit hash
|
|
210
|
+
- `data.last_commit.dt.date.long`: date as `%B %d, %Y` (e.g. `April 12, 2026`)
|
|
211
|
+
- `data.last_commit.dt.date.short`: date as `%Y-%m-%d` (e.g. `2026-04-12`)
|
|
212
|
+
- `data.last_commit.dt.time`: time as `%H:%M:%S`
|
|
213
|
+
- `data.last_commit.dt.iso`: datetime as ISO 8601
|
|
214
|
+
|
|
215
|
+
#### Regular page templates
|
|
216
|
+
|
|
217
|
+
- `page`: the current page
|
|
218
|
+
- `page.active_page`: identifier derived from the filename (e.g. `about` for `about.html`, `home` for `index.html`), useful for highlighting the active nav item
|
|
219
|
+
- `page.canonical_path`: URL path of the page (e.g. `/about`)
|
|
220
|
+
- `page.content`: page content as HTML (only present if the page has front matter)
|
|
221
|
+
- `page.metadata.<field>`: any front matter field (e.g. `page.metadata.title`)
|
|
222
|
+
|
|
223
|
+
#### Blog post template
|
|
224
|
+
|
|
225
|
+
- `page`: navigation info
|
|
226
|
+
- `page.active_page`: name of the blog directory (e.g. `blog`)
|
|
227
|
+
- `page.canonical_path`: URL path of the post (e.g. `/blog/my-post`)
|
|
228
|
+
- `post`: the current blog post
|
|
229
|
+
- `post.title`: post title (from front matter, or derived from the filename)
|
|
230
|
+
- `post.slug`: URL slug (filename without `.md`)
|
|
231
|
+
- `post.content`: post content as HTML
|
|
232
|
+
- `post.date`: date as `%Y-%m-%d` (e.g. `2026-04-12`), only set if a date is available
|
|
233
|
+
- `post.date_iso`: date as ISO 8601, only set if a date is available
|
|
234
|
+
- `data`: same as above
|
|
235
|
+
|
|
236
|
+
#### Blog index template
|
|
237
|
+
|
|
238
|
+
- `page`: navigation info
|
|
239
|
+
- `page.active_page`: name of the blog directory (e.g. `blog`)
|
|
240
|
+
- `page.canonical_path`: URL path of the blog index (e.g. `/blog`)
|
|
241
|
+
- `posts`: list of all blog posts sorted newest first; each item has the same fields as `post` above
|
|
242
|
+
- `data`: same as above
|
|
243
|
+
|
|
244
|
+
## CLI
|
|
245
|
+
|
|
246
|
+
```bash
|
|
247
|
+
# Build with default config (stapler.toml)
|
|
248
|
+
stapler build
|
|
249
|
+
|
|
250
|
+
# Build with custom config
|
|
251
|
+
stapler build -c myconfig.toml
|
|
252
|
+
|
|
253
|
+
# Serve on default port (8000)
|
|
254
|
+
stapler serve
|
|
255
|
+
|
|
256
|
+
# Serve on custom port
|
|
257
|
+
stapler serve -p 3000
|
|
258
|
+
|
|
259
|
+
# Serve with custom config and port
|
|
260
|
+
stapler serve -c myconfig.toml -p 3000
|
|
261
|
+
|
|
262
|
+
# Show version
|
|
263
|
+
stapler --version
|
|
264
|
+
```
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
body {
|
|
2
|
+
font-family: system-ui, sans-serif;
|
|
3
|
+
line-height: 1.6;
|
|
4
|
+
max-width: 800px;
|
|
5
|
+
margin: 0 auto;
|
|
6
|
+
padding: 20px;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
nav {
|
|
10
|
+
margin-bottom: 40px;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
nav a {
|
|
14
|
+
margin-right: 20px;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
article {
|
|
18
|
+
margin-bottom: 40px;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
footer {
|
|
22
|
+
margin-top: 80px;
|
|
23
|
+
padding-top: 20px;
|
|
24
|
+
border-top: 1px solid #ccc;
|
|
25
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: getting started
|
|
3
|
+
date: 2025-01-16
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# getting started with stapler
|
|
7
|
+
|
|
8
|
+
here's how to get started with your own stapler site.
|
|
9
|
+
|
|
10
|
+
## create a config
|
|
11
|
+
|
|
12
|
+
create `stapler.toml`:
|
|
13
|
+
|
|
14
|
+
```toml
|
|
15
|
+
[site]
|
|
16
|
+
url = "https://yoursite.com"
|
|
17
|
+
title = "your site"
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## add content
|
|
21
|
+
|
|
22
|
+
create a `site/` folder and put your content there. that's it!
|
|
23
|
+
|
|
24
|
+
## build
|
|
25
|
+
|
|
26
|
+
run `stapler build` to build your site, or `stapler serve` for a dev server.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: welcome to stapler
|
|
3
|
+
date: 2025-01-15
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# welcome to stapler
|
|
7
|
+
|
|
8
|
+
this is the first example blog post. stapler is a simple static site generator built with python.
|
|
9
|
+
|
|
10
|
+
## features
|
|
11
|
+
|
|
12
|
+
- jinja2 templating
|
|
13
|
+
- markdown support
|
|
14
|
+
- blog with rss/atom feeds
|
|
15
|
+
- dev server with live reload
|
|
16
|
+
|
|
17
|
+
## getting started
|
|
18
|
+
|
|
19
|
+
check out the [README](https://github.com/gijs6/stapler) for installation instructions.
|