Package: pyssg
pyssg - Static Site Generator written in PythonGenerates HTML files from MD files for a static site, personally using it for a blog-like site.Initially inspired by Roman Zolotarev'sssg5andrssg, Luke Smith'slbandsupand, pedantic.software'sblogit.Features and to-doNOTE:WIP, there will be changes that will breakpyssggenerations/config setup.Build static site parsingmarkdownfiles (*.md->*.html)Usesjinjafor templating.Preserves hand-made*.htmlfiles.Tag functionality, useful for blog-style sites.Buildsitemap.xmlfile.Include manually added*.htmlfiles.Buildrss.xmlfile.Include manually added*.htmlfiles.YAML for configuration file, usesPyYAML.Support for multiple "documents".PyYAMLsupports this. Inpyssgcontext, it means it can generate multiple websites (I personally use it for subdomains).Support for more complex directory structure to support configuration on a per directory basis.File checksum checking for modification of files.Option/change to using an SQL database instead of the custom solution.Use external markdown extensions.So far only extension configuration is for my own extensionpymdvar.Markdown featuresThis program uses the basemarkdownsyntaxplus additional syntax, all thanks topython-markdownthat providesextensions. The following extensions are used:Extra (collection of QoL extensions).Meta-Data.Sane Lists.SmartyPants.Table of Contents.Withpermalink=Trueandbaselevel=2, for more:python-markdown toc.WikiLinks.pymdvar(made by me).yafg - Yet Another Figure GeneratorMarkdown ChecklistPyMdown ExtensionsCaretTildeMarkInstallationInstall withpip:pipinstallpyssgProbably will add a PKBUILD (and possibly submit it to the AUR) in the future.UsageGet the default configuration file:pyssg--copy-default-config-c<path/to/config>Where-cis optional as by default$XDG_CONFIG_HOME/pyssg/config.yamlis used.Edit the config file created as needed.config.yamlis parsed usingPyYAML,more about the config file.Initialize the directory structures (source, destination, template) and move template files:pyssg-iYou can modify the basic templates as needed (seevariables available for Jinja).Strongly recommended to edit therss.xmltemplate.Place your*.mdfiles somewhere inside the source directory. It accepts sub-directories. Optionally configure for subdirectories if they are to be treated a bit different.Recommended (no longer mandatory) metadata keys that can be added to the top of.mdfiles: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
	etcYou can add more meta-data keys as long as it isPython-Markdown compliant, and these will veavailable as Jinja variablesin themetaobject (dict[str, Any]).Build the*.htmlwith:pyssg-bAfter this, you have ready to deploy*.htmlfiles from thedstdirectory.Config fileAll sections/options need to be compliant withPyYAMLwhich should be compliant withYAML 1.2. Additionaly, I've added the custom tag!joinwhich 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 produceother_variable: "valueother_value1". Alsoenvironment variables will be expanded internally.Note: URL's shouldn't have the trailing slash/.The following is a list of config items that need to be present in the config unless stated otherwise:%YAML1.2---# not needed, shown here as an example of the !join tagdefine:&root"$HOME/path/to/"# $HOME expands to /home/user, for exampletitle:"Examplesite"path:src:!join[*root,"src"]# $HOME/path/to/srcdst:"$HOME/some/other/path/to/dst"plt:"plt"db:!join[*root,"src/","db.psv"]url:main:"https://example.com"# I personally use a "static" url for images/scripts/css/etc, not necessarystatic:"https://static.example.com"fmt:date:"%a,%b%d,%Y@%H:%M%Z"list_date:"%b%d"# not necessarylist_sep_date:"%B%Y"# not necessarydirs:/:# root "dir_path", whatever is sitting directly under "src"cfg:plt:"page.html"# each page template, relative to path/plttags:Falseindex:Truerss:Truesitemap:Trueexclude_dirs:["articles","blog"]# optional; list of subdirs to exclude when parsing this "dir_path"...So far onlypymdvarcan be configured by including the following to the config:exts:pymdvar:variables:SOME_VAR:"somevalue"some_other_variable:123enable_env:True# to read environment variablesThe config underdirsare just per-subdirectory configuration of directories undersrc, which I called "dir_paths" for lack of creativity. Only the/"dir_path" is required as it is the config for the rootsrcpath files. Mandatory config items for each "dir_path":cfg:plt:"template.html"tags:Trueindex:Truerss:Truesitemap:Trueexclude:[]# not necessarySo that extra "dir_paths" can be added underdirs:dirs:/:cfg:...articles:cfg:...gallery:cfg:...etc:...The following will be added on runtime to the configuration:%YAML1.2---fmt:rss_date:"%a,%d%b%Y%H:%M:%SGMT"# fixedsitemap_date:"%Y-%m-%d"# fixedinfo:version:"x.y.z"# current 'pyssg' version (0.5.1.dev16, for example)debug:True/False# depending if --debug was used when executingrss_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.Available Jinja variablesThese variables are exposed to use within the templates. The below list is displayed in the form ofvariable (type) (available from): description.field1/field2/field3/...describe config file section from the YAML file and option andobject.attributecorresponding object and it's attribute.config(dict[str, Any]) (all): parsed config file plus the added options internally (as described inconfig file).dir_config(dict[str, Any]) (all*): parsed dir_config file plus the added options internally (as described inconfig file). *This is for all of the specific "dir_path" files, as per configured in the YAML filedirs.dir_path.cfg(for exmapledirs./.cfgfor 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*.mdfiles):title(str): title of the page.author(list[str]): list of authors of the page.lang(str): page language, used for the generalhtmltaglangattribute.summary(str): summary of the page, as specified in the*.mdfile.content(str): actual content of the page, this is thehtml.toc(str): table of contents as taken frommd.toc.toc_tokens(list[dict[str, Any]]): table of contents tokens as taken frommd.toc_tokens.cdatetime(datetime.datetime): creation datetime object of the page.cdate(method(FMT: str)): takes the name of thefmt.FMTand applies it to thecdatetimeobject.cdate_rss(str): formattedcdatetimeas required by rss.cdate_sitemap(str): formattedcdatetimeas required by sitemap.mdatetime(datetime.datetime): modification datetime object of the page. Defaults toNone.mdate(method(FMT: str)): takes the name of thefmt.FMTand applies it to themdatetimeobject.mdate_rss(str): formattedmdatetimeas required by rss.mdate_sitemap(str): formattedmdatetimeas required by sitemap.tags(list[tuple[str]]): list of tuple of tags of the page, containing the name and the url of the tag, respectively. Defaults to empty list.url(str): url of the page, this already includes theurl/mainfrom config file.next/previous(Page): reference to the next or previous page object (containing all these attributes). Defaults toNone.meta(dict[str, list[str]]): meta dict as obtained frompython-markdown, in case you use a meta tag not directly 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 toall_pagesbut contains all the pages for the current tag.all_tags(list[tuple[str]]) (all): similar topage.tagsbut contains all the tags.