A Static Site Generator using markdown files
Project description
# pyssg - Static Site Generator written in Python
Inspired (initially) by Roman Zolotarev’s [ssg5](https://rgz.ee/bin/ssg5) and [rssg](https://rgz.ee/bin/rssg), Luke Smith’s [lb and sup](https://github.com/LukeSmithxyz/lb) and, pedantic.software’s great (but “mamador”, as I would say in spanish) [blogit](https://pedantic.software/git/blogit/).
## Features and to-do
- [x] Build static site parsing markdown files ( *.md -> *.html)
- [x] ~~Using plain *.html files for templates.~~ Changed to Jinja templates.
[x] Would like to change to something more flexible and easier to manage ([jinja](https://jinja.palletsprojects.com/en/3.0.x/), for example).
[x] Preserves hand-made *.html files.
[x] Tag functionality.
[ ] Open Graph (and similar) support. (Technically, this works if you add the correct metadata to the *.md files and use the variables available for Jinja)
- [x] Build sitemap.xml file.
[ ] Include manually added *.html files.
- [x] Build rss.xml file.
[ ] Join the static_url to all relative URLs found to comply with the [RSS 2.0 spec](https://validator.w3.org/feed/docs/rss2.html) (this would be added to the parsed HTML text extracted from the MD files, so it would be available to the created *.html and *.xml files). Note that depending on the reader, it will append the URL specified in the RSS file or use the [xml:base](https://www.rssboard.org/news/151/relative-links) specified ([newsboat](https://newsboat.org/) parses xml:base).
[ ] Include manually added *.html files.
- [x] Only build page if *.md is new or updated.
[ ] Extend this to tag pages and index (right now all tags and index is built no matter if no new/updated file is present).
- [x] Configuration file. ~~as an alternative to using command line flags (configuration file options are prioritized).~~
[x] Use [configparser](https://docs.python.org/3/library/configparser.html) instead of custom config handler.
[ ] Migrate to YAML instead of INI, as it is way more flexible.
[x] Avoid the program to freak out when there are directories created in advance.
[x] Provide more meaningful error messages when you are missing mandatory metadata in your *.md files.
[ ] More complex directory structure to support multiple subdomains and different types of pages.
[ ] Add option/change to using an SQL database instead of the custom solution.
### Markdown features
This program uses the base [markdown syntax](https://daringfireball.net/projects/markdown/syntax) plus additional syntax, all thanks to [python-markdown](https://python-markdown.github.io/) that provides [extensions](https://python-markdown.github.io/extensions/). The following extensions are used:
Extra (collection of QoL extensions).
Meta-Data.
Sane Lists.
SmartyPants.
Table of Contents.
WikiLinks.
[yafg - Yet Another Figure Generator](https://git.sr.ht/~ferruck/yafg)
[markdown.highlight](https://github.com/ribalba/markdown.highlight)
[Markdown Checklist](https://github.com/FND/markdown-checklist)
## Installation
Just install it with pip:
`sh pip install pyssg `
Will add a PKBUILD (and possibly submit it to the AUR) sometime later.
## Usage
Get the default configuration file:
`sh pyssg --copy-default-config -c <path/to/config> `
Where -c is optional as by default $XDG_CONFIG_HOME/pyssg/config.ini is used.
Edit the config file created as needed.
config.ini is parsed using Python’s [configparser](https://docs.python.org/3/library/configparser.html), [more about the config file](#config-file).
Initialize the directory structures (source, destination, template) and move template files:
`sh pyssg -i `
You can modify the basic templates as needed (see [variables available for Jinja](#available-jinja-variables)).
Strongly recommended to edit the rss.xml template.
Place your *.md files somewhere inside the source directory. It accepts sub-directories.
Remember to add the mandatory meta-data keys to your .md files, these are:
` title: the title of your blog entry or whatever author: your name or online handle lang: the language the entry is written on summary: a summary of the entry `
You can add more meta-data keys as long as it is [Python-Markdown compliant](https://python-markdown.github.io/extensions/meta_data/), and these will ve [available as Jinja variables](#available-jinja-variables).
Also strongly recomended to add the tags metadata so that pyssg generates some nice filtering tags.
Build the *.html with:
`sh pyssg -b `
After this, you have ready to deploy *.html files.
For now, the building option also creates the rss.xml and sitemap.xml files based on templates, including only all converted *.md files (and processed tags in case of the sitemap), meaning that separate *.html files should be included manually in the template.
## Config file
All sections/options need to be compliant with the [configparser](https://docs.python.org/3/library/configparser.html).
At least the sections and options given in the default config should be present:
`ini [path] src=src # source dst=dst # destination plt=plt # template [url] main=https://example.com static=https://static.example.com # used for static resources (images, js, css, etc) default_image=/images/default.png # this will be appended to 'static' at the end [fmt] # % needs to be escaped with another % date=%%a, %%b %%d, %%Y @ %%H:%%M %%Z list_date=%%b %%d list_sep_date=%%B %%Y [info] title=Example site [other] force=False `
Along with these, these extra ones will be added on runtime:
`ini [fmt] rss_date=%%a, %%d %%b %%Y %%H:%%M:%%S GMT # fixed sitemap_date=%%Y-%%m-%%d # fixed [info] version= # current 'pyssg' version (0.5.1.dev16, for example) rss_run_date= # date the program was run, formatted with 'rss_date' sitemap_run_date= # date the program was run, formatted with 'sitemap_date' `
You can add any other option/section that you can later use in the Jinja templates via the exposed config object.
Other requisites are:
Urls shouldn’t have the trailing slash /.
The only character that needs to be escaped is % with another %.
## Available Jinja variables
These variables are exposed to use within the templates. The below list is in the form of variable (type) (available from): description. section/option describe config file section and option and object.attribute corresponding object and it’s attribute.
config (ConfigParser) (all): parsed config file plus the added options internally (as described in [config file](#config-file)).
all_pages (list(Page)) (all): list of all the pages, sorted by creation time, reversed.
- page (Page) (page.html): contains the following attributes (genarally these are parsed from the metadata in the *.md files):
title (str): title of the page.
author (str): author of the page.
content (str): actual content of the page, this is the html.
cdatetime (str): creation datetime object of the page.
cdate (str): formatted cdatetime as the config option fmt/date.
cdate_list (str): formatted cdatetime as the config option fmt/list_date.
cdate_list_sep (str): formatted cdatetime as the config option fmt/list_sep_date.
cdate_rss (str): formatted cdatetime as required by rss.
cdate_sitemap (str): formatted cdatetime as required by sitemap.
mdatetime (str): modification datetime object of the page. Defaults to None.
mdate (str): formatted mdatetime as the config option fmt/date. Defaults to None.
mdate_list (str): formatted mdatetime as the config option fmt/list_date.
mdate_list_sep (str): formatted mdatetime as the config option fmt/list_sep_date.
mdate_rss (str): formatted mdatetime as required by rss.
mdate_sitemap (str): formatted mdatetime as required by sitemap.
summary (str): summary of the page, as specified in the *.md file.
lang (str): page language, used for the general html tag lang attribute.
tags (list(tuple(str))): list of tuple of tags of the page, containing the name and the url of the tag, in that order. Defaults to empty list.
url (str): url of the page, this already includes the url/main from config file.
image_url (str): image url of the page, this already includes the url/static. Defaults to the url/default_image config option.
next/previous (Page): reference to the next or previous page object (containing all these attributes). Defaults to None.
og (dict(str, str)): dict for object graph metadata.
meta (dict(str, list(str))): meta dict as obtained from python-markdown, in case you use a meta tag not yet supported, it will be available there.
tag (tuple(str)) (tag.html): tuple of name and url of the current tag.
tag_pages (list(Page)) (tag.html): similar to all_pages but contains all the pages for the current tag.
all_tags (list(tuple(str))) (all): similar to page.tags but contains all the tags.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.