Generate static webpages (HTML files) suitable for uploading to a web hosting via FTP from Markdown documents formatted by Jinja2 templates and attach static resources (CSS, PNG, JPG files) used by the webpages.
Generate paginated lists sorted by date pointing to webpages marked by a tag.
Generate Google-compatible sitemap pointing to recent and selected documents and RSS/Atom feed pointing to recent documents.
Use URLs pointing either to local filesystem (file://
) for debugging
before publishing or to a webserver (http://
) for the publishing
to a real webserver.
- For each webpage of the website:
The user provides a document containing textual contents of the webpage and metadata selecting the template and features of the webpage. (*) - For each template referenced by the documents:
The user provides a template describing the appearance of the webpage. - For each static resource referenced by the documents and templates:
The user provides the resource file. - The user asks the generator to build the website from provided documents, templates and resources using local filesystem for the URLs.
- For each document:
The generator creates a webpage - For each tag referenced by the documents:
The generator creates paginated list sorted by date pointing to webpages marked by given tag. - The user displays and checks the generated webpage in a browser using files on the local filesystem.
- The user assk the generator to re-build the final version of the website using a remote webserver for the URLs.
- The user uploads the rebuilt website to the webhosting via FTP.
(*) The sitemap and RSS feed are regular documents with a corresponding
template (sitemap.xml
and atom.xml
).
python3 generator.py
Prerequisites: Python 3 (tested using Python 3.4.3 on Ubuntu 15.10)
git checkout https://github.com/TODO
pip install markdown jinja2
Each document consists of two parts, delimited by a blank line:
- Metadata: key:value dictionary with webpage metadata in YAML format
- Contents: text of the webpage in Markdown format
The metadata of each document should contain at least the following keys:
- template: mandatory for all documents, used for HTML/XML rendering
- date: mandatory for documents with a tag, used for paginated list sorting
- tags: mandatory for documents to be added to a paginated list
- title: recommended for SEO via HTML <title>
- description: recommended for SEO via HTML <meta name="description"/>
- keywords: recommended for SEO via HTML <meta name="keywords"/>
The template
value has to contain the whole filename, its suffix is used as a
suffix for the exported HTML/XML file to the filesystem.
Mandatory keys are used by the generator itself, recommended keys should be used by the templates (example templates do so), using any other keys is possible and purely depends on their usage in the templates. Missing keys are replaced by None. Keys and their values are case-sensitive, leading and trailing whitespaces are stripped out.
- Website
- Markdown documents:
documents/\*
- Jinja2 templates:
templates/\*.{html | xml}
- Static resources:
resources/\*.{jpg | png | css | ...}
- Generated website:
generated/\*.{html | xml}
- Markdown documents:
The references to images from Markdown use just the filename (with the file
extension and without quotes) and the generator automatically points them to the
resource folder (regardless if at the local filesystem or on a web server).
Example: ![picture.png](A picture)
is translated to
file:///home/user/generator/generated/static/picture.png
or to
http://website.domain/static/picture.png
Likewise, the links to another documents from the Markdown use just the document
name (without the file extension and without quotes) and the generator
automatically points them to the generated webpage for given document.
Example: [about-us](About us)
is translated to
file:///home/user/generator/generated/about-us.html
or to
http://website.domain/about-us.html
If a resource document or a document is located in a subfolder, the reference
from the Markdown should include the subfolder.
Example: [blog/interesting-blogpost](Interesting Blogpost)
is translated
to file:///home/user/generator/generated/blog/interesting-blogpost.html
or to
http://website.domain/blog/interesting-blogpost.html
The templates can leverage any features of Jinja2 templating engine, however the most useful ones are:
- Inheritance: a template can reuse parts of another template via
{% include %}
- Inclusion: a template can reuse an external file via
{% include %}
- Markdown: any part of the template/external file can use Markdown format
surrounded by
{% filter markdown %}
(do not indentat the Markdown contents otherwise it will be interpreted as preformatted) - Conditions: rendering of the document into HTML can depend on a value of given document's metadata (e. g. first page of a list) or a website-globals
- Loops: document's rendered HTML can contain repeating parts based on given document's metadata or website-globals (e .g. few newest blog posts)
Jinja2 templates do not support rendering of Markdown into HTML out of the box.
Generator implements a custom Jinja2 filter named markdown
which delegates
the rendering of Markdown to Python Markdown module.
If the template wraps the Markdown text by {% filter markdown %}
and
{% endfilter %}
, the rendered HTML is then added to the rendered webpage.
Example:
<html>
<head/>
<body>
{% filter markdown %}
{ document.markdown_contents }
{% endfilter %}
</body>
</html>
The generator provides a reference to the rendered document as document
(allowing access to the document's metadata) and a reference to a dictionary of
all documents of the website as documents
(allowing access to other
documents' metadata, useful for example for displaying last few blog posts in
the sidebar).
References to other documents must contain the whole filename (and canonical path relative to the site root if the referenced document is located in a subfolder), use document filenames without an extension.
The generator automatically generated webpages with a paginated list sorted by date with references to all documents having a tag. Attach a tag to all blog posts to have the timeline generated automatically.
The tag name serves as a name of virtual folder located under the site root (beware of conflicts with folder names of the documents).
The tag name with .html
suffix serves as a name of the template used for
rendering of all pages of the paginated timeline.
Categories can be also provided via the tags.
- Markdown Extension
- Replaces Markdown image links by
{{ resource() }}
placeholder
- Markdown Extension
- Replaces Markdown links by
{{ url_for() }}
placeholder
- One Markdown document
- Loads the document from filesystem, parses YAML metadata and Markdown contents
- All Jinja2 templates used by the website (including the paginated timelines)
- Loads the templates from filesystem
- Adds Markdown support to the templates
- Adds absolute URL support to the templates
- Adds current date and time support to the templates
- Adds custom template-globals to the templates
Uses: class ResourceExtension
, class UrlForExtension
, module Markdown
,
module Jinja2
- All webpages for the Markdown documents
- Loads all documents from the filesystem
- Renders all documents into HTML/XML
- Exports all rendered HTML/XMLs to the filesystem
- Finds the template for given document
- Injects reference to rendered document and to all documents into the template
Uses: class Templates
, class Document
list
- All pages of the paginated timeline
- Builds a timeline from all documents having given tag (by sorting them by date)
- Splits the timeline into pages holding piecemeals of the documents
- Finds neighbor pages to each timeline page
Uses: class Document
list
- All webpages for pages of one timeline
- Renders all pages of the timeline into HTML (XML is not supported)
- Exports all rendered HTML documents to the filesystem
Uses: class TimelinePages
- Finds all tags used by the website
- Builds the whole website
uses:
class DocumentGenerator
,class TimelinePagesGenerator
list, website root (commandline argument)