Skip to main content

A Static Site Generator using markdown files

Project description

pyssg - Static Site Generator written in Python

Generates HTML files from MD files for a static site, personally using it for a blog-like site.

Initially inspired by Roman Zolotarev's ssg5 and rssg, Luke Smith's lb and sup and, pedantic.software's blogit.

Features and to-do

NOTE: WIP, there will be changes that will break the setup.

  • Build static site parsing markdown files ( *.md -> *.html)
    • Uses jinja for templating.
    • Preserves hand-made *.html files.
    • Tag functionality, useful for blog-style sites.
    • 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.
  • Build sitemap.xml file.
    • Include manually added *.html files.
  • Build rss.xml file.
    • Join the static_url to all relative URLs found to comply with the RSS 2.0 spec.
      • 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 specified (for example, newsboat parses xml:base).
    • Include manually added *.html files.
  • YAML for configuration file, uses PyYAML.
    • Handle multiple "documents".
    • More complex directory structure to support multiple subdomains and different types of pages.
  • Option/change to using an SQL database instead of the custom solution.
  • Checksum checking because the timestamp of the file is not enough.
  • Use external markdown extensions.

Markdown features

This program uses the base markdown syntax plus additional syntax, all thanks to python-markdown that provides extensions. The following extensions are used:

Installation

Install with pip:

pip install pyssg

Probably will add a PKBUILD (and possibly submit it to the AUR) in the future.

Usage

  1. Get the default configuration file:
pyssg --copy-default-config -c <path/to/config>
  • Where -c is optional as by default $XDG_CONFIG_HOME/pyssg/config.yaml is used.
  1. Edit the config file created as needed.
  1. Initialize the directory structures (source, destination, template) and move template files:
pyssg -i
  1. Place your *.md files somewhere inside the source directory. It accepts sub-directories.
  • Recommended (no longer mandatory) metadata keys that can be added to the top of .md files:
title: the title of your blog entry or whatever
author: your name or online handle
	another name maybe for multiple authors?
lang: the language the entry is written on
summary: a summary of the entry
tags: english
	short
	tutorial
	etc
  1. Build the *.html with:
pyssg -b
  • After this, you have ready to deploy *.html files.

Config file

All sections/options need to be compliant with PyYAML which should be compliant with YAML 1.2. Additionaly, I've added the custom tag !join which concatenates strings from an array, which an be used as follows:

variable: &variable_reference_name "value"
other_variable: !join [*variable_reference_name, "other_value", 1]

Which would produce other_variable: "valueother_value1". Also environment variables will be expanded internally.

The following is a list of config items that need to be present in the config unless stated otherwise:

%YAML 1.2
---
# not needed, shown here as an example of the !join tag
define: &root "$HOME/path/to/" # $HOME expands to /home/user, for example

title: "Example site"
path:
  src: !join [*root, "src"] # $HOME/path/to/src
  dst: "$HOME/some/other/path/to/dst"
  plt: "plt"
  db: !join [*root, "src/", "db.psv"]
url:
  main: "https://example.com"
fmt:
  date: "%a, %b %d, %Y @ %H:%M %Z"
  list_date: "%b %d"
  list_sep_date: "%B %Y"
dirs:
  /: # root "dir_path", whatever is sitting directly under "src"
	cfg:
	  plt: "page.html"
	  # the template can be specified instead of just True/False, a default template will used
	  tags: False
	  index: True
	  rss: True
	  sitemap: True
	  exclude_dirs: ["articles", "blog"] # optional; list of subdirectories to exclude when parsing the / dir_path
# below are other example "dir_paths", can be named anything, only the / (above) is mandatory
  articles:
    cfg:
	  plt: "page.html"
	  tags: True
	  index: True
	  rss: True
	  sitemap: True
  blog:
    cfg:
	  # ...
...

The config under dirs are just per-subdirectory configuration of directories under src. Only the / "dir_path" is required as it is the config for the root src path files.

The following will be added on runtime:

%YAML 1.2
---
fmt:
  rss_date: "%a, %d %b %Y %H:%M:%S GMT" # fixed
  sitemap_date: "%Y-%m-%d" # fixed
info:
  version: "x.y.z" # current 'pyssg' version (0.5.1.dev16, for example)
  debug: True/False # depending if --debug was used when executing
  force: True/False # depending if --force was used when executing
rss_run_date: # date the program was run, formatted with 'fmt.rss_date'
sitemap_run_date: # date the program was run, formatted with 'fmt.sitemap_date'
...

You can add any other option/section that you can later use in the Jinja templates via the exposed config object. URL's shouldn't have the trailing slash /

Available Jinja variables

These variables are exposed to use within the templates. The below list is displayed in the form of variable (type) (available from): description. field1/field2/field3/... describe config file section from the YAML file and option and object.attribute corresponding object and it's attribute.

  • config (dict) (all): parsed config file plus the added options internally (as described in config file).
  • dir_config (dict) (all*): parsed dir_config file plus the added options internally (as described in config file). *This is for all of the specific "dir_path" files, as per configured in the YAML file dirs.dir_path.cfg (for exmaple dirs./.cfg for the required dir_path).
  • 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 (list[str]): list of authors of the page.
    • lang (str): page language, used for the general html tag lang attribute.
    • summary (str): summary of the page, as specified in the *.md file.
    • content (str): actual content of the page, this is the html.
    • cdatetime (datetime.datetime): creation datetime object of the page.
    • cdate (method): method thtat takes the name of the fmt.FMT and applies it to the cdatetime object.
    • cdate_rss (str): formatted cdatetime as required by rss.
    • cdate_sitemap (str): formatted cdatetime as required by sitemap.
    • mdatetime (datetime.datetime): modification datetime object of the page. Defaults to None.
    • mdate (method): method thtat takes the name of the fmt.FMT and applies it to the mdatetime object.
    • mdate_rss (str): formatted mdatetime as required by rss.
    • mdate_sitemap (str): formatted mdatetime as required by sitemap.
    • 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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pyssg-0.8.3.tar.gz (6.5 MB view hashes)

Uploaded Source

Built Distribution

pyssg-0.8.3-py3-none-any.whl (37.2 kB view hashes)

Uploaded Python 3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page