aerographite 1.0.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.
- aerographite-1.0.0/LICENSE +21 -0
- aerographite-1.0.0/PKG-INFO +95 -0
- aerographite-1.0.0/README.md +79 -0
- aerographite-1.0.0/aerographite.egg-info/PKG-INFO +95 -0
- aerographite-1.0.0/aerographite.egg-info/SOURCES.txt +12 -0
- aerographite-1.0.0/aerographite.egg-info/dependency_links.txt +1 -0
- aerographite-1.0.0/aerographite.egg-info/entry_points.txt +2 -0
- aerographite-1.0.0/aerographite.egg-info/top_level.txt +1 -0
- aerographite-1.0.0/pyproject.toml +45 -0
- aerographite-1.0.0/setup.cfg +4 -0
- aerographite-1.0.0/src/aerographite/__init__.py +4 -0
- aerographite-1.0.0/src/aerographite/__main__.py +4 -0
- aerographite-1.0.0/src/aerographite/config_template.yaml +10 -0
- aerographite-1.0.0/src/aerographite/litestatic.py +207 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Alice
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: aerographite
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Tiny lightweight static site generator written in Python that uses markdown and liquid to generate a website.
|
|
5
|
+
Author-email: Alice Sell <alice@alicela1n.space>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://gitlab.com/alicela1n/aerographite
|
|
8
|
+
Project-URL: Issues, https://gitlab.com/alicela1n/aerographite/issues
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: Operating System :: OS Independent
|
|
11
|
+
Classifier: Environment :: Web Environment
|
|
12
|
+
Requires-Python: >=3.9
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
License-File: LICENSE
|
|
15
|
+
Dynamic: license-file
|
|
16
|
+
|
|
17
|
+
<a href='https://ko-fi.com/S6S2A9XRF' target='_blank'><img height='36' style='border:0px;height:36px;' src='https://storage.ko-fi.com/cdn/kofi6.png?v=6' border='0' alt='Buy Me a Coffee at ko-fi.com' /></a>
|
|
18
|
+
|
|
19
|
+
# Aerographite
|
|
20
|
+
Tiny lightweight static site generator written in Python that uses markdown and liquid to generate a website.
|
|
21
|
+
|
|
22
|
+
# How it works
|
|
23
|
+
The way it works is simple by design. The `aerographite` script checks for a `site` directory, which is your website's source directory. A template `site_template` is provided as a submodule, which can be copied and modified for your site. The `(site_directory)/templates` directory contains [liquid](https://shopify.github.io/liquid/) templates for generating the html skeleton of your website. [Markdown](https://www.markdownguide.org/) is used for the webpage contents. The index.md is the markdown file that generates the front page of the website.
|
|
24
|
+
|
|
25
|
+
You can put markdown files in the site directory and have them generated as `(site_directory)/(page name)`. You can also put html in the markdown files and it will render in the body.To customize the html outside the body use templates. For javascript you can source your scripts either in the markdown files or html template. You can also have blog-style posts by putting markdown files in the `site/(posts_directory)/` directory. `posts_directory` is by default `posts`.
|
|
26
|
+
|
|
27
|
+
The name for the posts needs to be formatted as: `(posts_directory)/YYYY-MM-DD-title.md`.
|
|
28
|
+
|
|
29
|
+
The posts need to have a metadata header:
|
|
30
|
+
```
|
|
31
|
+
title: Post Title
|
|
32
|
+
date: YYYY-MM-DD HH:mm
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Posts will be indexed in `/posts` which you can link in index.md or anywhere else.
|
|
36
|
+
|
|
37
|
+
The `(site_directory)/files/` directory is for any miscellaneous files that get copied to the output directory `out/`.
|
|
38
|
+
|
|
39
|
+
The generated website is outputted to the output directory ready to be deployed to a web server or wherever.
|
|
40
|
+
|
|
41
|
+
# Configuration
|
|
42
|
+
You can configure many things, such as blog post generation, the name of the index page, rss feed generation, and the posts directory.
|
|
43
|
+
|
|
44
|
+
To configure these things, copy the `config_template.yaml` to your site directory.
|
|
45
|
+
|
|
46
|
+
If you change the `posts_directory` you must also rename it in your site directory, since that is the directory it will look for at generation time. This will change the url where your posts are, for example if you want it to be `/blog` such as `example.com/blog` change the `posts_directory` to `blog`.
|
|
47
|
+
|
|
48
|
+
# RSS Feed Generation
|
|
49
|
+
You can generate an RSS feed `(posts_directory)/rss.xml` by setting `rss_feed_generation` in the `config.yaml` to `True`. You need to set a `site_url`, `language`, and `feed_description`. If you do not set an `index_page_title` it uses the `site_url` as the RSS feed title.
|
|
50
|
+
|
|
51
|
+
# Installation
|
|
52
|
+
If you want to install aerographite from the pip repositories, run:
|
|
53
|
+
```
|
|
54
|
+
$ pip3 install aerographite
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
If youw want to install aerographite from this repo, follow these instructions:
|
|
58
|
+
|
|
59
|
+
First you need to install the requirements:
|
|
60
|
+
```
|
|
61
|
+
$ pip3 install -r requirements.txt
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Next, install aerographite using pip:
|
|
65
|
+
```
|
|
66
|
+
$ python3 -m pip install .
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
# How to use
|
|
70
|
+
|
|
71
|
+
Provide your own site directory or use the template and modify it to your needs:
|
|
72
|
+
```
|
|
73
|
+
$ git submodule update --init
|
|
74
|
+
$ cp site-template (site_location)
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Next, edit the site how you see fit.
|
|
78
|
+
|
|
79
|
+
Finally, to generate a website run:
|
|
80
|
+
```
|
|
81
|
+
$ aerographite (site_directory) (output_directory)
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
To view your website locally, run a web server:
|
|
85
|
+
```
|
|
86
|
+
$ python3 -m http.server -d (output_directory)
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
# Screenshots
|
|
90
|
+
Here are some screenshots of the example site to demonstrate what aerographite can do.
|
|
91
|
+
|
|
92
|
+

|
|
93
|
+

|
|
94
|
+

|
|
95
|
+

|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
<a href='https://ko-fi.com/S6S2A9XRF' target='_blank'><img height='36' style='border:0px;height:36px;' src='https://storage.ko-fi.com/cdn/kofi6.png?v=6' border='0' alt='Buy Me a Coffee at ko-fi.com' /></a>
|
|
2
|
+
|
|
3
|
+
# Aerographite
|
|
4
|
+
Tiny lightweight static site generator written in Python that uses markdown and liquid to generate a website.
|
|
5
|
+
|
|
6
|
+
# How it works
|
|
7
|
+
The way it works is simple by design. The `aerographite` script checks for a `site` directory, which is your website's source directory. A template `site_template` is provided as a submodule, which can be copied and modified for your site. The `(site_directory)/templates` directory contains [liquid](https://shopify.github.io/liquid/) templates for generating the html skeleton of your website. [Markdown](https://www.markdownguide.org/) is used for the webpage contents. The index.md is the markdown file that generates the front page of the website.
|
|
8
|
+
|
|
9
|
+
You can put markdown files in the site directory and have them generated as `(site_directory)/(page name)`. You can also put html in the markdown files and it will render in the body.To customize the html outside the body use templates. For javascript you can source your scripts either in the markdown files or html template. You can also have blog-style posts by putting markdown files in the `site/(posts_directory)/` directory. `posts_directory` is by default `posts`.
|
|
10
|
+
|
|
11
|
+
The name for the posts needs to be formatted as: `(posts_directory)/YYYY-MM-DD-title.md`.
|
|
12
|
+
|
|
13
|
+
The posts need to have a metadata header:
|
|
14
|
+
```
|
|
15
|
+
title: Post Title
|
|
16
|
+
date: YYYY-MM-DD HH:mm
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Posts will be indexed in `/posts` which you can link in index.md or anywhere else.
|
|
20
|
+
|
|
21
|
+
The `(site_directory)/files/` directory is for any miscellaneous files that get copied to the output directory `out/`.
|
|
22
|
+
|
|
23
|
+
The generated website is outputted to the output directory ready to be deployed to a web server or wherever.
|
|
24
|
+
|
|
25
|
+
# Configuration
|
|
26
|
+
You can configure many things, such as blog post generation, the name of the index page, rss feed generation, and the posts directory.
|
|
27
|
+
|
|
28
|
+
To configure these things, copy the `config_template.yaml` to your site directory.
|
|
29
|
+
|
|
30
|
+
If you change the `posts_directory` you must also rename it in your site directory, since that is the directory it will look for at generation time. This will change the url where your posts are, for example if you want it to be `/blog` such as `example.com/blog` change the `posts_directory` to `blog`.
|
|
31
|
+
|
|
32
|
+
# RSS Feed Generation
|
|
33
|
+
You can generate an RSS feed `(posts_directory)/rss.xml` by setting `rss_feed_generation` in the `config.yaml` to `True`. You need to set a `site_url`, `language`, and `feed_description`. If you do not set an `index_page_title` it uses the `site_url` as the RSS feed title.
|
|
34
|
+
|
|
35
|
+
# Installation
|
|
36
|
+
If you want to install aerographite from the pip repositories, run:
|
|
37
|
+
```
|
|
38
|
+
$ pip3 install aerographite
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
If youw want to install aerographite from this repo, follow these instructions:
|
|
42
|
+
|
|
43
|
+
First you need to install the requirements:
|
|
44
|
+
```
|
|
45
|
+
$ pip3 install -r requirements.txt
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Next, install aerographite using pip:
|
|
49
|
+
```
|
|
50
|
+
$ python3 -m pip install .
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
# How to use
|
|
54
|
+
|
|
55
|
+
Provide your own site directory or use the template and modify it to your needs:
|
|
56
|
+
```
|
|
57
|
+
$ git submodule update --init
|
|
58
|
+
$ cp site-template (site_location)
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Next, edit the site how you see fit.
|
|
62
|
+
|
|
63
|
+
Finally, to generate a website run:
|
|
64
|
+
```
|
|
65
|
+
$ aerographite (site_directory) (output_directory)
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
To view your website locally, run a web server:
|
|
69
|
+
```
|
|
70
|
+
$ python3 -m http.server -d (output_directory)
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
# Screenshots
|
|
74
|
+
Here are some screenshots of the example site to demonstrate what aerographite can do.
|
|
75
|
+
|
|
76
|
+

|
|
77
|
+

|
|
78
|
+

|
|
79
|
+

|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: aerographite
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Tiny lightweight static site generator written in Python that uses markdown and liquid to generate a website.
|
|
5
|
+
Author-email: Alice Sell <alice@alicela1n.space>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://gitlab.com/alicela1n/aerographite
|
|
8
|
+
Project-URL: Issues, https://gitlab.com/alicela1n/aerographite/issues
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: Operating System :: OS Independent
|
|
11
|
+
Classifier: Environment :: Web Environment
|
|
12
|
+
Requires-Python: >=3.9
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
License-File: LICENSE
|
|
15
|
+
Dynamic: license-file
|
|
16
|
+
|
|
17
|
+
<a href='https://ko-fi.com/S6S2A9XRF' target='_blank'><img height='36' style='border:0px;height:36px;' src='https://storage.ko-fi.com/cdn/kofi6.png?v=6' border='0' alt='Buy Me a Coffee at ko-fi.com' /></a>
|
|
18
|
+
|
|
19
|
+
# Aerographite
|
|
20
|
+
Tiny lightweight static site generator written in Python that uses markdown and liquid to generate a website.
|
|
21
|
+
|
|
22
|
+
# How it works
|
|
23
|
+
The way it works is simple by design. The `aerographite` script checks for a `site` directory, which is your website's source directory. A template `site_template` is provided as a submodule, which can be copied and modified for your site. The `(site_directory)/templates` directory contains [liquid](https://shopify.github.io/liquid/) templates for generating the html skeleton of your website. [Markdown](https://www.markdownguide.org/) is used for the webpage contents. The index.md is the markdown file that generates the front page of the website.
|
|
24
|
+
|
|
25
|
+
You can put markdown files in the site directory and have them generated as `(site_directory)/(page name)`. You can also put html in the markdown files and it will render in the body.To customize the html outside the body use templates. For javascript you can source your scripts either in the markdown files or html template. You can also have blog-style posts by putting markdown files in the `site/(posts_directory)/` directory. `posts_directory` is by default `posts`.
|
|
26
|
+
|
|
27
|
+
The name for the posts needs to be formatted as: `(posts_directory)/YYYY-MM-DD-title.md`.
|
|
28
|
+
|
|
29
|
+
The posts need to have a metadata header:
|
|
30
|
+
```
|
|
31
|
+
title: Post Title
|
|
32
|
+
date: YYYY-MM-DD HH:mm
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Posts will be indexed in `/posts` which you can link in index.md or anywhere else.
|
|
36
|
+
|
|
37
|
+
The `(site_directory)/files/` directory is for any miscellaneous files that get copied to the output directory `out/`.
|
|
38
|
+
|
|
39
|
+
The generated website is outputted to the output directory ready to be deployed to a web server or wherever.
|
|
40
|
+
|
|
41
|
+
# Configuration
|
|
42
|
+
You can configure many things, such as blog post generation, the name of the index page, rss feed generation, and the posts directory.
|
|
43
|
+
|
|
44
|
+
To configure these things, copy the `config_template.yaml` to your site directory.
|
|
45
|
+
|
|
46
|
+
If you change the `posts_directory` you must also rename it in your site directory, since that is the directory it will look for at generation time. This will change the url where your posts are, for example if you want it to be `/blog` such as `example.com/blog` change the `posts_directory` to `blog`.
|
|
47
|
+
|
|
48
|
+
# RSS Feed Generation
|
|
49
|
+
You can generate an RSS feed `(posts_directory)/rss.xml` by setting `rss_feed_generation` in the `config.yaml` to `True`. You need to set a `site_url`, `language`, and `feed_description`. If you do not set an `index_page_title` it uses the `site_url` as the RSS feed title.
|
|
50
|
+
|
|
51
|
+
# Installation
|
|
52
|
+
If you want to install aerographite from the pip repositories, run:
|
|
53
|
+
```
|
|
54
|
+
$ pip3 install aerographite
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
If youw want to install aerographite from this repo, follow these instructions:
|
|
58
|
+
|
|
59
|
+
First you need to install the requirements:
|
|
60
|
+
```
|
|
61
|
+
$ pip3 install -r requirements.txt
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Next, install aerographite using pip:
|
|
65
|
+
```
|
|
66
|
+
$ python3 -m pip install .
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
# How to use
|
|
70
|
+
|
|
71
|
+
Provide your own site directory or use the template and modify it to your needs:
|
|
72
|
+
```
|
|
73
|
+
$ git submodule update --init
|
|
74
|
+
$ cp site-template (site_location)
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Next, edit the site how you see fit.
|
|
78
|
+
|
|
79
|
+
Finally, to generate a website run:
|
|
80
|
+
```
|
|
81
|
+
$ aerographite (site_directory) (output_directory)
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
To view your website locally, run a web server:
|
|
85
|
+
```
|
|
86
|
+
$ python3 -m http.server -d (output_directory)
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
# Screenshots
|
|
90
|
+
Here are some screenshots of the example site to demonstrate what aerographite can do.
|
|
91
|
+
|
|
92
|
+

|
|
93
|
+

|
|
94
|
+

|
|
95
|
+

|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
aerographite.egg-info/PKG-INFO
|
|
5
|
+
aerographite.egg-info/SOURCES.txt
|
|
6
|
+
aerographite.egg-info/dependency_links.txt
|
|
7
|
+
aerographite.egg-info/entry_points.txt
|
|
8
|
+
aerographite.egg-info/top_level.txt
|
|
9
|
+
src/aerographite/__init__.py
|
|
10
|
+
src/aerographite/__main__.py
|
|
11
|
+
src/aerographite/config_template.yaml
|
|
12
|
+
src/aerographite/litestatic.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
aerographite
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools >= 77.0.3"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "aerographite"
|
|
7
|
+
version = "1.0.0"
|
|
8
|
+
authors = [
|
|
9
|
+
{ name="Alice Sell", email="alice@alicela1n.space" },
|
|
10
|
+
]
|
|
11
|
+
description = "Tiny lightweight static site generator written in Python that uses markdown and liquid to generate a website."
|
|
12
|
+
readme = {file = "README.md", content-type = "text/markdown"}
|
|
13
|
+
requires-python = ">=3.9"
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Programming Language :: Python :: 3",
|
|
16
|
+
"Operating System :: OS Independent",
|
|
17
|
+
"Environment :: Web Environment",
|
|
18
|
+
]
|
|
19
|
+
license = "MIT"
|
|
20
|
+
license-files = ["LICEN[CS]E*"]
|
|
21
|
+
|
|
22
|
+
[tool.setuptools]
|
|
23
|
+
packages = ["aerographite"]
|
|
24
|
+
|
|
25
|
+
[tool.setuptools.package-dir]
|
|
26
|
+
aerographite = "src/aerographite"
|
|
27
|
+
|
|
28
|
+
[tool.setuptools.package-data]
|
|
29
|
+
"aerographite" = ["*.yaml"]
|
|
30
|
+
|
|
31
|
+
install_requires = [
|
|
32
|
+
"feedgen",
|
|
33
|
+
"marko",
|
|
34
|
+
"python-frontmatter",
|
|
35
|
+
"python-liquid",
|
|
36
|
+
"pygments",
|
|
37
|
+
"pyyaml"
|
|
38
|
+
]
|
|
39
|
+
|
|
40
|
+
[project.scripts]
|
|
41
|
+
aerographite = "aerographite:main"
|
|
42
|
+
|
|
43
|
+
[project.urls]
|
|
44
|
+
Homepage = "https://gitlab.com/alicela1n/aerographite"
|
|
45
|
+
Issues = "https://gitlab.com/alicela1n/aerographite/issues"
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
blog_post_generation: True
|
|
2
|
+
index_page_title:
|
|
3
|
+
posts_directory: posts
|
|
4
|
+
|
|
5
|
+
# Needed for RSS feed generation
|
|
6
|
+
generate_rss_feed: False
|
|
7
|
+
site_url:
|
|
8
|
+
url_prefix: # Example: http:// or https:// or https://www. (if you use http to https redirection you you could use http here for better compatibility with proxy servers)
|
|
9
|
+
language: en
|
|
10
|
+
feed_description:
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
from marko import Markdown
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from liquid import Template
|
|
5
|
+
from liquid import Environment
|
|
6
|
+
from liquid import FileSystemLoader
|
|
7
|
+
import os
|
|
8
|
+
import shutil
|
|
9
|
+
import frontmatter
|
|
10
|
+
import datetime
|
|
11
|
+
markdown = Markdown(extensions=['codehilite'])
|
|
12
|
+
import pygments
|
|
13
|
+
import yaml
|
|
14
|
+
import argparse
|
|
15
|
+
from importlib.resources import files
|
|
16
|
+
from feedgen.feed import FeedGenerator
|
|
17
|
+
|
|
18
|
+
# Each post is a markdown file which gets parsed into an object which contains it's metadata, date,
|
|
19
|
+
# and HTML content (converted from the Markdown).
|
|
20
|
+
class Post:
|
|
21
|
+
def __init__(self, name, title, date, html):
|
|
22
|
+
self.name = name
|
|
23
|
+
self.title = title
|
|
24
|
+
self.date = datetime.datetime.strptime(date, '%Y-%m-%d %H:%M').replace(tzinfo=datetime.timezone.utc)
|
|
25
|
+
self.html = html
|
|
26
|
+
|
|
27
|
+
# Command line argument parser
|
|
28
|
+
parser = argparse.ArgumentParser()
|
|
29
|
+
parser.add_argument("site_directory", type=str, help="The website source directory to be generated")
|
|
30
|
+
parser.add_argument("output_directory", type=str, help="The directory to output the generated website")
|
|
31
|
+
|
|
32
|
+
# generate_index_page(): Produce the index.html file which will be the front page of the website
|
|
33
|
+
def generate_index_page(index_page_title, site_directory, templates_directory, output_directory):
|
|
34
|
+
env = Environment(loader=FileSystemLoader(f"{site_directory}/{templates_directory}/"))
|
|
35
|
+
template = env.get_template("index.html")
|
|
36
|
+
|
|
37
|
+
if not os.path.exists(f"{output_directory}"):
|
|
38
|
+
os.makedirs(f"{output_directory}")
|
|
39
|
+
|
|
40
|
+
with open(f"{site_directory}/index.md", "r") as index_file:
|
|
41
|
+
index_buffer = frontmatter.load(index_file)
|
|
42
|
+
index_body = markdown.convert(index_buffer.content)
|
|
43
|
+
|
|
44
|
+
with open(f"{output_directory}/index.html", "w") as output_file:
|
|
45
|
+
print(f"Generating {output_directory}/index.html")
|
|
46
|
+
output_file.write(template.render(page_title=index_page_title,index_body=index_body,))
|
|
47
|
+
|
|
48
|
+
# generate_html_pages(): Produce the HTML pages out of markdown files that will make up the site
|
|
49
|
+
def generate_html_pages(site_directory, templates_directory, output_directory):
|
|
50
|
+
env = Environment(loader=FileSystemLoader(f"{site_directory}/{templates_directory}/"))
|
|
51
|
+
|
|
52
|
+
if not os.path.exists(f"{output_directory}"):
|
|
53
|
+
os.makedirs(f"{output_directory}")
|
|
54
|
+
|
|
55
|
+
page_files = Path(site_directory).glob("*.md")
|
|
56
|
+
for page in page_files:
|
|
57
|
+
with open(page, "r") as md_file:
|
|
58
|
+
page_buffer = frontmatter.load(md_file)
|
|
59
|
+
page_body = markdown.convert(page_buffer.content)
|
|
60
|
+
page_name = str(page.with_suffix(''))
|
|
61
|
+
page_name = page_name.split('/')[-1]
|
|
62
|
+
|
|
63
|
+
if not page_name == "index": # Exclude index
|
|
64
|
+
if not os.path.exists(f"{output_directory}/{page_name}"):
|
|
65
|
+
os.makedirs(f"{output_directory}/{page_name}")
|
|
66
|
+
|
|
67
|
+
if os.path.exists(f"{site_directory}/{templates_directory}/{page_name}.html"):
|
|
68
|
+
template = env.get_template(f"{page_name}.html")
|
|
69
|
+
else:
|
|
70
|
+
template = env.get_template("page.html")
|
|
71
|
+
|
|
72
|
+
with open(f"{output_directory}/{page_name}/index.html", "w") as output_file:
|
|
73
|
+
print(f"Generating {output_directory}/{page_name}/index.html")
|
|
74
|
+
output_file.write(template.render(page_title=page_name, page_body=page_body,))
|
|
75
|
+
|
|
76
|
+
# generate_posts(): Produce an array of post objects
|
|
77
|
+
def generate_posts(site_directory, posts_directory):
|
|
78
|
+
post_files = Path(f"{site_directory}/{posts_directory}").glob("*.md")
|
|
79
|
+
|
|
80
|
+
posts = []
|
|
81
|
+
for post in post_files:
|
|
82
|
+
with open(post, "r") as md_file:
|
|
83
|
+
# Remove the extension from the post name
|
|
84
|
+
post_name = str(post.with_suffix(''))
|
|
85
|
+
# Remove the site_directory and post_directory from the post name
|
|
86
|
+
post_name = post_name.split('/')[-1]
|
|
87
|
+
|
|
88
|
+
post_buffer = frontmatter.load(md_file)
|
|
89
|
+
post_title = post_buffer['title']
|
|
90
|
+
post_date = post_buffer['date']
|
|
91
|
+
post_html = markdown.convert(post_buffer.content)
|
|
92
|
+
posts.append(Post(post_name, post_title, post_date, post_html))
|
|
93
|
+
|
|
94
|
+
return posts
|
|
95
|
+
|
|
96
|
+
# generate_post_files(): Generate the html files for the posts
|
|
97
|
+
def generate_post_files(posts, site_directory, templates_directory, posts_directory, output_directory):
|
|
98
|
+
env = Environment(loader=FileSystemLoader(f"{site_directory}/{templates_directory}/"))
|
|
99
|
+
template = env.get_template("post-template.html")
|
|
100
|
+
|
|
101
|
+
if not os.path.exists(f"{output_directory}/{posts_directory}"):
|
|
102
|
+
os.makedirs(f"{output_directory}/{posts_directory}")
|
|
103
|
+
|
|
104
|
+
for post in posts:
|
|
105
|
+
if not os.path.exists(f"{output_directory}/{posts_directory}/{post.name}"):
|
|
106
|
+
os.makedirs(f"{output_directory}/{posts_directory}/{post.name}")
|
|
107
|
+
|
|
108
|
+
with open(f"{output_directory}/{posts_directory}/{post.name}/index.html", "w") as output_file:
|
|
109
|
+
print(f"Generating {output_directory}/{posts_directory}/{post.name}")
|
|
110
|
+
output_file.write(template.render(page_title=post.title, post_title=post.title, post_date=post.date, post_html=post.html,))
|
|
111
|
+
|
|
112
|
+
# generate_post_index(): Generate the post index
|
|
113
|
+
def generate_post_index(posts, site_directory, templates_directory, posts_directory, output_directory):
|
|
114
|
+
posts_list = []
|
|
115
|
+
|
|
116
|
+
for post in posts:
|
|
117
|
+
posts_dict = {"title": post.title, "date": post.date, "path": f"{post.name}"}
|
|
118
|
+
posts_list.append(posts_dict)
|
|
119
|
+
|
|
120
|
+
posts_data = { "posts" : posts_list }
|
|
121
|
+
|
|
122
|
+
env = Environment(loader=FileSystemLoader(f"{site_directory}/{templates_directory}/"))
|
|
123
|
+
template = env.get_template("posts-index.html")
|
|
124
|
+
|
|
125
|
+
with open(f"{output_directory}/{posts_directory}/index.html", "w") as output_file:
|
|
126
|
+
print(f"Generating {output_directory}/{posts_directory}/index.html")
|
|
127
|
+
output_file.write(template.render(page_title="Posts", **posts_data))
|
|
128
|
+
|
|
129
|
+
# generate_rss_feed: Generate an RSS feed and populate it with your blog posts
|
|
130
|
+
def generate_rss_feed(posts, feed_title, feed_description, site_url, url_prefix, language, output_directory, posts_directory):
|
|
131
|
+
feed = FeedGenerator()
|
|
132
|
+
feed.title(feed_title)
|
|
133
|
+
feed.description(feed_description)
|
|
134
|
+
feed.language(language)
|
|
135
|
+
feed.id(f"posts")
|
|
136
|
+
feed.link( href=f"{site_url}/{posts_directory}", rel='self')
|
|
137
|
+
# Use post metadata for RSS feed
|
|
138
|
+
for post in posts:
|
|
139
|
+
feed_entry = feed.add_entry()
|
|
140
|
+
feed_entry.id(f"{post.name}")
|
|
141
|
+
feed_entry.title(post.title)
|
|
142
|
+
feed_entry.content(content=post.html, type='text/html')
|
|
143
|
+
feed_entry.pubDate(post.date)
|
|
144
|
+
feed_entry.link(href=f"{url_prefix}{site_url}/{posts_directory}/{post.name}")
|
|
145
|
+
|
|
146
|
+
feed.atom_file(f"{output_directory}/{posts_directory}/rss.xml", pretty=True)
|
|
147
|
+
|
|
148
|
+
# copy_files_to_out(): Copy the files in the files directory to the output directory
|
|
149
|
+
def copy_files_to_out(site_directory, files_directory, output_directory):
|
|
150
|
+
shutil.copytree(f"{site_directory}/{files_directory}", output_directory, symlinks=False, ignore=None, copy_function=shutil.copy2, ignore_dangling_symlinks=False, dirs_exist_ok=True)
|
|
151
|
+
|
|
152
|
+
# main(): Main function
|
|
153
|
+
def main():
|
|
154
|
+
args = parser.parse_args()
|
|
155
|
+
site_directory = args.site_directory
|
|
156
|
+
files_directory = "files"
|
|
157
|
+
templates_directory = "templates"
|
|
158
|
+
config_template_path = files("litestatic").joinpath("config_template.yaml")
|
|
159
|
+
|
|
160
|
+
if site_directory == ".":
|
|
161
|
+
site_directory = Path.cwd()
|
|
162
|
+
|
|
163
|
+
if not os.path.exists(site_directory):
|
|
164
|
+
print("No site directory found!")
|
|
165
|
+
print("Provide a site directory or create one using the site_template!")
|
|
166
|
+
exit();
|
|
167
|
+
|
|
168
|
+
output_directory = args.output_directory
|
|
169
|
+
if not os.path.exists(output_directory):
|
|
170
|
+
os.makedirs(output_directory)
|
|
171
|
+
|
|
172
|
+
if os.path.isfile(f"{site_directory}/config.yaml"):
|
|
173
|
+
config = yaml.safe_load(Path(f"{site_directory}/config.yaml").read_text()) # Read the config file
|
|
174
|
+
else:
|
|
175
|
+
config = yaml.safe_load(Path(config_template_path).read_text()) # Fall back to config_template.yaml
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
index_page_title = config["index_page_title"]
|
|
179
|
+
generate_index_page(index_page_title, site_directory, templates_directory, output_directory)
|
|
180
|
+
generate_html_pages(site_directory, templates_directory, output_directory)
|
|
181
|
+
|
|
182
|
+
# Fall back to posts if posts_directory not set
|
|
183
|
+
if config["blog_post_generation"] == True:
|
|
184
|
+
if config["posts_directory"]:
|
|
185
|
+
posts_directory = config["posts_directory"]
|
|
186
|
+
else:
|
|
187
|
+
posts_directory = "posts"
|
|
188
|
+
|
|
189
|
+
posts = generate_posts(site_directory, posts_directory)
|
|
190
|
+
generate_post_files(posts, site_directory, templates_directory, posts_directory, output_directory)
|
|
191
|
+
generate_post_index(posts, site_directory, templates_directory, posts_directory, output_directory)
|
|
192
|
+
|
|
193
|
+
# RSS feed generation
|
|
194
|
+
if config["generate_rss_feed"] == True:
|
|
195
|
+
site_url = config["site_url"]
|
|
196
|
+
url_prefix = config["url_prefix"]
|
|
197
|
+
language = config["language"]
|
|
198
|
+
feed_description = config["feed_description"]
|
|
199
|
+
# Get the index_page_title from the site url if not set explicitly
|
|
200
|
+
if not index_page_title:
|
|
201
|
+
index_page_title = f"{site_url}"
|
|
202
|
+
generate_rss_feed(posts, index_page_title, feed_description, site_url, url_prefix, language, output_directory, posts_directory)
|
|
203
|
+
|
|
204
|
+
copy_files_to_out(site_directory, files_directory, output_directory)
|
|
205
|
+
|
|
206
|
+
if __name__ == '__main__':
|
|
207
|
+
main()
|