blag - blag 1.4.1
blag is a blog-aware, static site generator, written in
Python. An
example "deployment" can be found
here.
blag is named after the blag of the webcomic
xkcd.
- •
- Write content in Markdown
- •
- Theming support using Jinja2 templates
- •
- Generation of Atom feeds for blog content
- •
- Fenced code blocks and syntax highlighting using
Pygments
- •
- Integrated devserver
- •
- Available on PyPI
blag runs on Linux, Mac and Windows and requires Python >= 3.8
Install blag from
PyPI
Run blag's quickstart command to create the configuration needed
Create some content
$ mkdir content
$ edit content/hello-world.md
Generate the website
By default, blag will search for content in
content and the output will
be generated in
build. All markdown files in
content will be
converted to html, all other files (i.e. static files) will be copied over).
If you want more separation between the static files and the markdown content,
you can put all static files into the
static directory. Blag will copy
them over to the
build directory.
If you want to customize the looks of the generated site, create a
template directory and put your jinja2 templates here.
Those directories can be changed via command line arguments. See
Internally, blag differentiates between
pages and
articles.
Intuitively, pages are simple pages and articles are blog posts. The decision
whether a document is a page or an article is made depending on the presence
of the
date metadata element: Any document that contains the
date metadata element is an article, everything else a page.
This differentiation has consequences:
- •
- blag uses different templates: page.html and
article.html
- •
- only articles are collected in the Atom feed
- •
- only articles are aggregated in the tag pages
blag does
not enforce a certain directory structure for pages and
articles. You can mix and match them freely or structure them in different
directories. blag will mirror the structure found in the
content
directory
content/
article1.md
article2.md
page1.md
results in:
build/
article1.html
article2.html
page1.html
Arbitrary complex structures are possible too:
content/
posts/
2020/
2020-01-01-foo.md
2020-02-01-foo.md
pages/
foo.md
bar.md
results in:
build/
posts/
2020/
2020-01-01-foo.html
2020-02-01-foo.html
pages/
foo.html
bar.html
Static files can be put into the
content directory and will be copied
over to the
build directory as well. If you want better separation
between content and static files, you can create a
static directory and
put the files there. All files and directories found in the
static
directory will be copied over to
build.
content/
foo.md
bar.md
kitty.jpg
results in:
build/
foo.html
bar.html
kitty.jpg
Alternatively:
content/
foo.md
bar.md
static/
kitty.jpg
results in:
build/
foo.html
bar.html
kitty.jpg
In contrast to most other static blog generators, blag will automatically
convert
relative markdown links. That means you can link you content
using relative markdown links and blag will convert them to html
automatically. The advantage is that your content tree in markdown is
consistent and self-contained even if you don't generate html from it.
[...]
this is a [link](foo.md) to an internal page foo.
becomes
<p>this is a <a href="foo.html">link</a> to an internal page foo.</p>
Custom templates are
optional and stored by default in the
templates directory. blag will search the
templates directory
first, and fall back to blag's default built-in templates.
|
Template |
Used For |
Variables |
|
page.html |
pages (i.e. non-articles) |
site, content, meta |
|
article.html |
articles (i.e. blog posts) |
site, content, meta |
|
archive.html |
archive- and landing page of the blog |
site, archive |
|
tags.html |
list of tags |
site, tags |
|
tag.html |
archive of Articles with a certain tag |
site, archive, tag |
|
If you make use of Jinja2's template inheritance, you can of course have more
template files in the
templates directory.
- site
- This dictionary contains the site configuration, namely:
base_url, title, description and author. Don't
confuse the site-title and -description with the title and description of
individual pages or articles.
- content
- HTML, converted from markdown.
- meta
-
meta stands for all metadata elements available in
the article or page. Please be aware that those are not wrapped in a
dictionary, but directly available as variables.
- archive
- A list of [destination path, context] tuples, where
the context are the respective variables that would be provided to the
individual page or article.
- tags
- List of tags.
- tag
- A tag.
blag supports metadata elements in the markdown files. They must come before the
content and should be separated from the content with a blank line:
title: foo
date: 2020-02-02
tags: this, is, a, test
description: some subtitle
this is my content.
[...]
blag supports
arbitrary metadata in your documents, and you can use them
freely in you templates. However, some metadata elements are treated special:
- date
- If a document contains the date element, it is
treated as an article, otherwise as a page. Additionally,
date elements are expected to be in ISO format (e.g. 1980-05-05
21:58). They are automatically converted into datetime objects
with the local timezone attached.
- tags
- Tags are interpreted as a comma separated list. All
elements are stripped and converted to lower-case: tags: foo, Foo Bar,
BAZ becomes: [foo, foo bar, baz].
Tags in articles are also used to generate the tag-pages, that
aggregate all articles per tag.
- title and description
- The title and description are used in the html header and
in the atom feed.
blag provides a devserver which you can use for local web-development. The
devserver provides a simple web server, serving your site in
http://localhost:8000 and will automatically rebuild the project when
it detects modifications in one of the
content,
static and
templates directories.
|
blag.__init__ |
Initialize self. |
|
blag.version |
|
|
blag.blag |
blag's core methods. |
|
blag.markdown |
Markdown Processing. |
|
blag.devserver |
Development Server. |
|
blag.quickstart |
Helper methods for blag's quickstart command. |
|
- blag.__init__ = <method-wrapper '__init__' of module
object>
- Initialize self. See help(type(self)) for accurate
signature.
blag's core methods.
Functions
|
build(args) |
Build the site. |
|
environment_factory([template_dir, globals_]) |
Environment factory. |
|
generate_archive(articles, template, output_dir) |
Generate the archive page. |
|
generate_feed(articles, output_dir, ...) |
Generate Atom feed. |
|
generate_tags(articles, tags_template, ...) |
Generate the tags page. |
|
get_config(configfile) |
Load site configuration from configfile. |
|
main([arguments]) |
Main entrypoint for the CLI. |
|
parse_args([args]) |
Parse command line arguments. |
|
process_markdown(convertibles, input_dir, ...) |
Process markdown files. |
|
- blag.blag.build(args: argparse.Namespace) ->
None
- Build the site.
This is blag's main method that builds the site, generates the feed
etc.
- blag.blag.environment_factory(template_dir:
Optional[str] = None, globals_: Optional[dict[str, object]] = None) ->
jinja2.environment.Environment
- Environment factory.
Creates a Jinja2 Environment with the default templates and additional
templates from template_dir loaded. If globals are provided,
they are attached to the environment and thus available to all
contexts.
- Parameters
- •
-
template_dir -- directory containing the
templates
- •
-
globals --
- Return type
- jinja2.Environment
- blag.blag.generate_archive(articles: list[tuple[str,
dict[str, Any]]], template: jinja2.environment.Template, output_dir: str)
-> None
- Generate the archive page.
- Parameters
- •
-
articles -- List of articles. Each article has the
destination path and a dictionary with the content.
- •
-
template --
- •
-
output_dir --
- blag.blag.generate_feed(articles: list[tuple[str,
dict[str, Any]]], output_dir: str, base_url: str, blog_title: str,
blog_description: str, blog_author: str) -> None
- Generate Atom feed.
- Parameters
- •
-
articles -- list of relative output path and article
dictionary
- •
-
output_dir -- where the feed is stored
- •
-
base_url -- base url
- •
-
blog_title -- blog title
- •
-
blog_description -- blog description
- •
-
blog_author -- blog author
- blag.blag.generate_tags(articles: list[tuple[str,
dict[str, Any]]], tags_template: jinja2.environment.Template, tag_template:
jinja2.environment.Template, output_dir: str) -> None
- Generate the tags page.
- Parameters
- •
-
articles -- List of articles. Each article has the
destination path and a dictionary with the content.
- •
-
tags_template --
- •
-
tag_template --
- •
-
output_dir --
- blag.blag.get_config(configfile: str) ->
configparser.SectionProxy
- Load site configuration from configfile.
- Parameters
-
configfile -- path to configuration file
- Return type
- configparser.SectionProxy
- blag.blag.main(arguments: Optional[list[str]] = None)
-> None
- Main entrypoint for the CLI.
This method parses the CLI arguments and executes the respective
commands.
- Parameters
-
arguments -- optional parameters, used for
testing
- blag.blag.parse_args(args: Optional[list[str]] = None)
-> argparse.Namespace
- Parse command line arguments.
- Parameters
-
args -- optional parameters, used for testing
- Return type
- arparse.Namespace
- blag.blag.process_markdown(convertibles: list[tuple[str,
str]], input_dir: str, output_dir: str, page_template:
jinja2.environment.Template, article_template: jinja2.environment.Template)
-> tuple[list[tuple[str, dict[str, Any]]], list[tuple[str, dict[str,
Any]]]]
- Process markdown files.
This method processes the convertibles, converts them to html and saves them
to the respective destination paths.
If a markdown file has a date metadata field it will be recognized as
article otherwise as page.
- Parameters
- •
-
convertibles -- relative paths to markdown- (src)
html- (dest) files
- •
-
input_dir --
- •
-
output_dir --
- •
-
page_template -- templats for pages and
articles
- •
-
archive_template -- templats for pages and
articles
- Returns
- articles and pages
- Return type
- list[tuple[str, dict[str, Any]]], list[tuple[str, dict[str,
Any]]]
Markdown Processing.
This module contains the methods responsible for blag's markdown processing.
Functions
|
convert_markdown(md, markdown) |
Convert markdown into html and extract meta data. |
|
markdown_factory() |
Create a Markdown instance. |
|
Classes
|
MarkdownLinkExtension(**kwargs) |
markdown.extension that converts relative .md- to .html-links. |
|
MarkdownLinkTreeprocessor([md]) |
Converts relative links to .md files to .html |
|
- class
blag.markdown.MarkdownLinkExtension(**kwargs)
- markdown.extension that converts relative .md- to
.html-links.
- __module__ = 'blag.markdown'
- extendMarkdown(md: markdown.core.Markdown) ->
None
- Add the various processors and patterns to the Markdown
Instance.
This method must be overridden by every extension.
Keyword arguments:
- •
- md: The Markdown instance.
- class
blag.markdown.MarkdownLinkTreeprocessor(md=None)
- Converts relative links to .md files to .html
- __module__ = 'blag.markdown'
- run(root: xml.etree.ElementTree.Element) ->
xml.etree.ElementTree.Element
- Subclasses of Treeprocessor should implement a run
method, which takes a root ElementTree. This method can return another
ElementTree object, and the existing root ElementTree will be replaced, or
it can modify the current tree and return None.
- blag.markdown.convert_markdown(md:
markdown.core.Markdown, markdown: str) -> tuple[str, dict[str,
str]]
- Convert markdown into html and extract meta data.
- Some meta data is treated special:
- •
-
date is converted into datetime with local
timezone
- •
-
tags is interpreted as a comma-separeted list of
strings. All strings are stripped and converted to lower case.
- Parameters
- •
-
md -- the Markdown instance
- •
-
markdown -- the markdown text that should be
converted
- Returns
- html and metadata
- Return type
- str, dict[str, str]
- blag.markdown.markdown_factory() ->
markdown.core.Markdown
- Create a Markdown instance.
This method exists only to ensure we use the same Markdown instance for
tests as for the actual thing.
- Return type
- markdown.Markdown
Development Server.
This module provides functionality for blag's development server. It
automatically detects changes in certain directories and rebuilds the site if
necessary.
Functions
|
autoreload(args) |
Start the autoreloader. |
|
get_last_modified(dirs) |
Get the last modified time. |
|
serve(args) |
Start the webserver and the autoreloader. |
|
- blag.devserver.autoreload(args: argparse.Namespace)
-> NoReturn
- Start the autoreloader.
This method monitors the given directories for changes (i.e. the last
modified time). If the last modified time has changed, a rebuild is
triggered.
A rebuild is also performed immediately when this method is called to avoid
serving stale contents.
- Parameters
-
args -- contains the input-, template- and static
dir
- blag.devserver.get_last_modified(dirs: list[str]) ->
float
- Get the last modified time.
This method recursively goes through dirs and returns the most recent
modification time time found.
- Parameters
-
dirs -- list of directories to search
- Returns
- most recent modification time found in dirs
- Return type
- float
- blag.devserver.serve(args: argparse.Namespace) ->
None
- Start the webserver and the autoreloader.
- Parameters
-
args -- contains the input-, template- and static
dir
Helper methods for blag's quickstart command.
Functions
|
get_input(question, default) |
Prompt for user input. |
|
quickstart(args) |
Quickstart. |
|
- blag.quickstart.get_input(question: str, default: str)
-> str
- Prompt for user input.
This is a wrapper around the input-builtin. It will show the default answer
in the prompt and -- if no answer was given -- use the default.
- Parameters
- •
-
question -- the question the user is presented
- •
-
default -- the default value that will be used if no
answer was given
- Returns
- the answer
- Return type
- str
- blag.quickstart.quickstart(args: argparse.Namespace |
None) -> None
- Quickstart.
This method asks the user some questions and generates a configuration file
that is needed in order to run blag.
- Parameters
-
args -- not used
- •
- Index
- •
- Module Index
- •
- Search Page
Bastian Venthur
2022, Bastian Venthur