├── .changelog_fragments ├── 1.0 │ ├── 1-initial-release.yaml │ └── release_meta.yml ├── 1.1 │ ├── 3-validate-options.yml │ ├── 4-fix-dynamic-word-wrap-limit.yml │ ├── 5-add-opengraph-support.yml │ ├── 6-add-logo-support-rss.yml │ └── release_meta.yml ├── 1.2 │ ├── 11-add-greyscale-theme.yml │ ├── 7-favicon-support.yml │ ├── 8-add-language-type-html-element.yml │ ├── 9-twitter-card-support.yml │ └── release_meta.yml ├── 1.3.1 │ ├── 17-fix-rss-feed.yml │ └── release_meta.yml └── 1.3 │ ├── 14-add-grey-blue-theme.yml │ ├── 15-add-initial-tag-support.yml │ ├── 15-add-meta-keyword-support.yml │ ├── 16-add-meta-robot-support.yml │ └── release_meta.yml ├── .gitignore ├── CHANGELOG.md ├── CONTRIBUTING.md ├── Dockerfile ├── LICENSE.md ├── README.md ├── _assets └── css │ ├── dark.css │ ├── grey.css │ ├── grey_blue.css │ ├── light.css │ ├── light_blue.css │ └── manpageblog.css ├── _templates ├── feed.xml ├── item.html ├── item.xml ├── list.html ├── page.html ├── page_tags.html └── post.html ├── blog.conf ├── content ├── _index.html ├── about.html ├── blog │ ├── 2023-11-11-manpageblog-release-1-0.md │ ├── 2023-11-13-manpageblog-now-available-in-freebsd-ports.md │ ├── 2023-11-15-manpageblog-release-1-1.md │ ├── 2023-11-21-manpageblog-in-the-1-mb-website-club.md │ ├── 2023-11-22-manpageblog-release-1-2.md │ ├── 2023-12-15-manpageblock-container-image-for-docker-podman.md │ ├── 2024-01-09-manpageblog-release-1-3.md │ ├── 2024-01-14-manpageblog-release-1-3-1.md │ └── 2024-06-06-manpageblog-release-1.4.md └── contact.html └── manpageblog /.changelog_fragments/1.0/1-initial-release.yaml: -------------------------------------------------------------------------------- 1 | added: 2 | - Initial release of the manpageblog (creates version 1.0) (#1) 3 | - Added darkmode support (#1) 4 | - Added manpage style layout (#1) 5 | - Added multi blog support (#1) 6 | - Added dynmaic template, assets and output support (#1) 7 | -------------------------------------------------------------------------------- /.changelog_fragments/1.0/release_meta.yml: -------------------------------------------------------------------------------- 1 | date: 2023-11-11 2 | -------------------------------------------------------------------------------- /.changelog_fragments/1.1/3-validate-options.yml: -------------------------------------------------------------------------------- 1 | fixed: 2 | - Validate function for passed options (#3) 3 | -------------------------------------------------------------------------------- /.changelog_fragments/1.1/4-fix-dynamic-word-wrap-limit.yml: -------------------------------------------------------------------------------- 1 | fixed: 2 | - Fix dynamic word wrap limit of words (#4) 3 | -------------------------------------------------------------------------------- /.changelog_fragments/1.1/5-add-opengraph-support.yml: -------------------------------------------------------------------------------- 1 | added: 2 | - Add Open Graph support for social media platforms (#5) 3 | -------------------------------------------------------------------------------- /.changelog_fragments/1.1/6-add-logo-support-rss.yml: -------------------------------------------------------------------------------- 1 | added: 2 | - Add logo (site_image) support for RSS feed (#6) 3 | -------------------------------------------------------------------------------- /.changelog_fragments/1.1/release_meta.yml: -------------------------------------------------------------------------------- 1 | date: 2023-11-14 2 | -------------------------------------------------------------------------------- /.changelog_fragments/1.2/11-add-greyscale-theme.yml: -------------------------------------------------------------------------------- 1 | added: 2 | - Add grey scaled CSS theme [#11] 3 | -------------------------------------------------------------------------------- /.changelog_fragments/1.2/7-favicon-support.yml: -------------------------------------------------------------------------------- 1 | added: 2 | - Add possibility to add different favicons [#7] 3 | - Allow external sources for favicons [#7] 4 | -------------------------------------------------------------------------------- /.changelog_fragments/1.2/8-add-language-type-html-element.yml: -------------------------------------------------------------------------------- 1 | fixed: 2 | - Fixed missing language type in html element [#8] 3 | -------------------------------------------------------------------------------- /.changelog_fragments/1.2/9-twitter-card-support.yml: -------------------------------------------------------------------------------- 1 | added: 2 | - Add Twitter Card support [#9] 3 | -------------------------------------------------------------------------------- /.changelog_fragments/1.2/release_meta.yml: -------------------------------------------------------------------------------- 1 | date: 2023-11-22 2 | -------------------------------------------------------------------------------- /.changelog_fragments/1.3.1/17-fix-rss-feed.yml: -------------------------------------------------------------------------------- 1 | fixed: 2 | - Fixed RSS XML feed to be RFC conform [#17] 3 | -------------------------------------------------------------------------------- /.changelog_fragments/1.3.1/release_meta.yml: -------------------------------------------------------------------------------- 1 | date: 2024-01-14 2 | -------------------------------------------------------------------------------- /.changelog_fragments/1.3/14-add-grey-blue-theme.yml: -------------------------------------------------------------------------------- 1 | added: 2 | - Add grey/blue scaled CSS theme [#14] 3 | -------------------------------------------------------------------------------- /.changelog_fragments/1.3/15-add-initial-tag-support.yml: -------------------------------------------------------------------------------- 1 | added: 2 | - Add initial support for tags [#15] 3 | -------------------------------------------------------------------------------- /.changelog_fragments/1.3/15-add-meta-keyword-support.yml: -------------------------------------------------------------------------------- 1 | added: 2 | - Add support for meta keywords [#15] 3 | -------------------------------------------------------------------------------- /.changelog_fragments/1.3/16-add-meta-robot-support.yml: -------------------------------------------------------------------------------- 1 | added: 2 | - Add support for meta robot options [#16] 3 | -------------------------------------------------------------------------------- /.changelog_fragments/1.3/release_meta.yml: -------------------------------------------------------------------------------- 1 | date: 2024-01-09 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | _site 2 | *.pyc 3 | __pycache__ 4 | .coverage 5 | htmlcov 6 | *.sw? 7 | .DS_Store 8 | venv 9 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 7 | 8 | 9 | ## [1.4] - 2024-06-06 10 | 11 | ### Added 12 | 13 | - Add link tag for RSS feed [#21] 14 | 15 | ### Fixed 16 | 17 | - Mobile website layout [#20] 18 | - Optimized retro browser support [#19] 19 | - Replace commonmark (deprecated) with markdown_it [#22] 20 | - CSS and font improvements [#24] 21 | 22 | 23 | ## [1.3.1] - 2024-01-14 24 | 25 | ### Fixed 26 | 27 | - Fixed RSS XML feed to be RFC conform [#17] 28 | 29 | 30 | ## [1.3] - 2024-01-09 31 | 32 | ### Added 33 | 34 | - Add grey/blue scaled CSS theme [#14] 35 | - Add support for meta keywords [#15] 36 | - Add support for meta robot options [#16] 37 | - Add initial support for tags [#15] 38 | 39 | 40 | ## [1.2] - 2023-11-22 41 | 42 | ### Added 43 | 44 | - Add Twitter Card support [#9] 45 | - Add grey scaled CSS theme [#11] 46 | - Add possibility to add different favicons [#7] 47 | - Allow external sources for favicons [#7] 48 | 49 | ### Fixed 50 | 51 | - Fixed missing language type in html element [#8] 52 | 53 | 54 | ## [1.1] - 2023-11-14 55 | 56 | ### Added 57 | 58 | - Add logo (site_image) support for RSS feed (#6) 59 | - Add Open Graph support for social media platforms (#5) 60 | 61 | ### Fixed 62 | 63 | - Fix dynamic word wrap limit of words (#4) 64 | - Validate function for passed options (#3) 65 | 66 | 67 | ## [1.0] - 2023-11-11 68 | 69 | ### Added 70 | 71 | - Initial release of the manpageblog (creates version 1.0) (#1) 72 | - Added darkmode support (#1) 73 | - Added manpage style layout (#1) 74 | - Added multi blog support (#1) 75 | - Added dynmaic template, assets and output support (#1) 76 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Contribution Guidelines 2 | ======================= 3 | 4 | Please take care of the following points while sending a pull request to 5 | this project: 6 | 7 | 1. Ensure that the pull request does not add major features or increase 8 | the scope of the project. Bug fixes and minor improvements are okay 9 | and might be accepted. But major features or changes that increase 10 | the complexity of the code will not be accepted. 11 | 12 | 2. Follow [PEP 8][CODING-GUIDE] while editing [manpageblog]. 13 | 14 | 3. Use only Makefile syntax, shell syntax, commands, and options that 15 | are specified in [POSIX][POSIX-HOME] as much as possible while 16 | editing [Makefile]. Avoid Bash-specific and GNU-specific features. 17 | See documentation on [POSIX Shell Command Language][POSIX-SCL], 18 | [POSIX Utilities][POSIX-UTIL], and [POSIX Make][POSIX-MAKE] for 19 | reference. 20 | 21 | 4. Follow [Erlang/OTP commit message guidelines][COMMIT-GUIDE] while 22 | writing Git commit messages. 23 | 24 | 25 | [manpageblog]: manpageblog 26 | [Makefile]: Makefile 27 | [POSIX-HOME]: https://pubs.opengroup.org/onlinepubs/9699919799/ 28 | [POSIX-SCL]: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html 29 | [POSIX-UTIL]: https://pubs.opengroup.org/onlinepubs/9699919799/idx/utilities.html 30 | [POSIX-MAKE]: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/make.html 31 | [CODING-GUIDE]: https://www.python.org/dev/peps/pep-0008/ 32 | [COMMIT-GUIDE]: https://github.com/erlang/otp/wiki/Writing-good-commit-messages 33 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # syntax=docker/dockerfile:1 2 | 3 | FROM debian 4 | 5 | # Labels 6 | LABEL maintainer="gyptazy@gyptazy.ch" 7 | LABEL org.label-schema.schema-version="1.0" 8 | LABEL org.label-schema.description="Manpageblog on nginx." 9 | LABEL org.label-schema.url="https://manpageblog.org/" 10 | 11 | RUN apt update && \ 12 | apt install -y git nginx python3 && \ 13 | mkdir /opt/manpageblog/ && \ 14 | cd /opt/manpageblog && \ 15 | git clone https://github.com/gyptazy/manpageblog.git && \ 16 | cd /opt/manpageblog/manpageblog && \ 17 | /opt/manpageblog/manpageblog/manpageblog && \ 18 | cp -r /opt/manpageblog/manpageblog/docroot/* /var/www/html/ 19 | 20 | EXPOSE 8080 21 | CMD ["nginx", "-g", "daemon off;"] 22 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | ===================== 3 | Copyright (c) 2023 Florian Paul Azim Hoberg @gyptazy 4 | All rights reserved 5 | 6 | This software is a derivative of the original makesite.py. 7 | The license text of the original makesite.py is included below. 8 | 9 | Copyright (c) 2018-2022 Sunaina Pai 10 | 11 | Permission is hereby granted, free of charge, to any person obtaining 12 | a copy of this software and associated documentation files (the 13 | "Software"), to deal in the Software without restriction, including 14 | without limitation the rights to use, copy, modify, merge, publish, 15 | distribute, sublicense, and/or sell copies of the Software, and to 16 | permit persons to whom the Software is furnished to do so, subject to 17 | the following conditions: 18 | 19 | The above copyright notice and this permission notice shall be 20 | included in all copies or substantial portions of the Software. 21 | 22 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 23 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 24 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 25 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 26 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 27 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 28 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # manpageblog 2 | 3 |
4 | 5 |

6 | 7 | 8 | ## Table of Content 9 | - [General](#general) 10 | - [Usage](#usage) 11 | - [Options](#options) 12 | - [Config File](#config-file) 13 | - [Blog entries (elements)](#blog-entries-elements) 14 | - [Quick-Start](#quick-start) 15 | - [Screenshots](#screenshots) 16 | - [Light Theme](#light-theme) 17 | - [Dark Theme](#dark-theme) 18 | - [Live Demo](#live-demo) 19 | - [Instances](#instances) 20 | - [Motivation](#motivation) 21 | - [License](#license) 22 | 23 | ## General 24 | `manpageblog` is a small, lightweight blog engine written in Python and offers several advantages in a look of a man page (Unix like manual page). Firstly, it provides simplicity and ease of use, making it accessible even for users with limited technical knowledge. The lightweight nature ensures quick installation and minimal resource consumption, making it suitable for various hosting environments. No database is needed at all. 25 | 26 | Python's readability and straightforward syntax make the blog engine easy to customize and extend, allowing users to tailor it to their specific needs. Additionally, being Python-based means leveraging a vast ecosystem of libraries and frameworks, enhancing the blog's functionality without unnecessary complexity. Posts and pages are written in Markdown or HTML while the blog engine generates the whole website. While using only flat files, this offers great possibilities in maintaining the content. Given this approach, you can manage your whole blog in git. 27 | 28 | The lightweight nature also contributes to faster loading times, improving user experience and search engine rankings. Overall, a small, lightweight blog engine in Python combines simplicity, flexibility, and efficiency, making it an ideal choice for those prioritizing a streamlined and customizable blogging experience. 29 | 30 | To support this small and lightweight expression of the blog engine the default theme represents a `man page` (manual page or also known as handbook) design which provides all needed information in a simple document. 31 | 32 | ## Usage 33 | `manpageblog` is a pretty easy, slim and straight forward tool. After checking out this repository it is enough to simply run the following command: 34 | ``` 35 | $> ./manpageblog 36 | ``` 37 | This command directly creates an example blog within the subdirectory `docroot` by the given example content from `content`. 38 | 39 | Adding and modifying content is only done within the `content` directory. This approach makes it easy to obtain the content for the blog from a git repository. All content is provided by flat files like `.md` (Markdown) and/or `.html`. 40 | 41 | ### Options 42 | `manpageblog` supports the following options: 43 | 44 | | Option | Example | Description | 45 | |------|:------:|------:| 46 | | -c | -c gyptazy.conf | Defines a config file for a specific blog | 47 | | -h | --help | Prints the help page | 48 | 49 | By creating multiple config files and adjusting them to dedicated output directories (and if needed templates & assets), this provides a multi blog setup. 50 | 51 | ### Config File 52 | The configuration file (default `blog.conf`) provides the following configuration files. You may adjust them to your personal needs: 53 | 54 | 55 | #### [general] 56 | | Option | Example | Description | 57 | |------|:------:|------:| 58 | | name | manpageblog | Defines the first part of the title (and HTML title) | 59 | | subtitle | a small and lightweight blog engine. | Defines the second part of the title (and HTML title) | 60 | | description | This is the blog of manpageblog where you can find more information | Defines the HTML meta descriptions (for searchengines) | 61 | | keywords | manpageblog, simple, easy, lightweight, blog engine | Keywords and tags as a comma separated list | 62 | | keywords_show | `meta` or `html` | Meta: Keywords will only be used for `meta` section. If `html` a tag section will be created | 63 | | robots | `noindex,nofollow` or `index,follow` | Defines if a page should be indexed by search engines (can be set for each site) | 64 | | author | admin | A default name for the author of blog posts | 65 | | copyright | manpageblog | name of a copyright holder | 66 | | preview_words | 150 (default) | How many words should be displayed within the blog index page | 67 | | logo_site | https://cdn.gyptazy.ch/images/manpageblog.jpg | URL to a default site logo (e.g. used for RSS) | 68 | | logo_favicon | https://cdn.gyptazy.ch/images/manpageblog.jpg | URL to a favicon image | 69 | | logo_apple_touch | https://cdn.gyptazy.ch/images/manpageblog.jpg | URL to an image for Apple Touch Icon (Webapp) | 70 | 71 | 72 | #### [social] 73 | | Option | Example | Description | 74 | |------|:------:|------:| 75 | | mastodon | https://mastodon.bsd.cafe/@manpageblog | Link to Mastodon profile | 76 | | twitter | @manpageblog | Twitter profile handle | 77 | | github | https://github.com/manpageblog | Link to GitHub profile | 78 | 79 | 80 | #### [opengraph] 81 | | Option | Example | Description | 82 | |------|:------:|------:| 83 | | image_width | 800 | Image width within the OG preview | 84 | | image_height | 375 | Image height within the OG preview | 85 | 86 | 87 | #### [processing] 88 | | Option | Example | Description | 89 | |------|:------:|------:| 90 | | site_url | http://localhost:8000 | URI (site url) where this blog is hosted | 91 | | base_path | None | Path to the blog (subdirectory, if not in docroot) | 92 | | assets_path | _assets | Path to the manpageblog assets | 93 | | template_path | _templates | Path to the manpageblog assets | 94 | | output_path | docroot | Output path to the generated blog | 95 | | theme | light | Defines the theme to use | 96 | 97 | ### Blog entries (elements) 98 | Within each website element or blog post, a custom title, meta description and an Open Graph image URL can be defined. This ones should be defined 99 | as comments which will re replaced and integrate during the site creation by the blog engine. 100 | 101 | #### Example Post 102 | ``` 103 | 104 | 105 | 106 | 107 | manpageblog finally got its first release. With version 1.0 a public release is now present. 108 | A small, lightweight blog engine written in Python and offers several advantages in a look 109 | of a man page (Unix like manual page). 110 | ``` 111 | 112 | 113 | #### Element Options 114 | | Option | Example | Description | 115 | |------|:------:|------:| 116 | | title: | manpageblog released in version 1.0 | HTML & OG title | 117 | | meta_description: | Initial release of manpageblog 1.0. A simple and static blog generator in manpage design written in Python. | HTML & OG description | 118 | | image_url: | https://cdn.gyptazy.ch/manpageblog.jpg | Path to an image file for Open Graph | 119 | 120 | 121 | ## Quick-Start 122 | To give this just a short test you can just run the following commands: 123 | ``` 124 | git clone https://github.com/gyptazy/manpageblog.git 125 | cd manpageblog 126 | ./manpageblog 127 | cd docroot 128 | python3 -m http.server 129 | ``` 130 | Afterwards, just open your browser and visit `http://localhost:8000`. That's it! 131 | 132 | ## Docker 133 | Another possibility to test manpageblog is given by container images. Where you can just rebuild the image by the given `Dockerfile` or by using a ready to use image. 134 | 135 | The fastest way results in using the ready to use image with the following commands: 136 | ``` 137 | docker pull cnt-reg.gyptazy.ch/gyptazy/manpageblog:1.2 138 | docker run -d --name manpageblog12 -p 8080:80 cnt-reg.gyptazy.ch/gyptazy/manpageblog:1.2 139 | 140 | # Use service on port tcp/8080 141 | curl localhost:8080 142 | ``` 143 | 144 | ## Screenshots 145 | ### Light Theme 146 | 147 | 148 | ### Dark Theme 149 | 150 | 151 | ## Live Demo 152 | A live demo of a running manpageblog instance can be found here:
153 | https://manpageblog.org 154 | 155 | ## Instances 156 | If you are using `manpageblog` you may add your website, blog or site here to share the usage and experience with other users. Of course, only if you like. 157 | 158 | **Instances**: 159 | | Website | User | Description | 160 | |------|:------:|------:| 161 | | https://manpageblog.org | @gyptazy | manpageblog project website | 162 | | https://gyptazy.ch | @gyptazy | DevOps, coding, cloud and open-source in a geeky way. Find out more about Ansible, Kubernetes, Prometheus and other fancy tools. You see code - I see bugs! | 163 | | https://boxybsd.com | BoxyBSD | BoxyBSD is a destination for free BSD-focused solutions and services for the community. | 164 | 165 | ## Motivation 166 | Like probably the most ones I started with `Wordpress` which is a pretty cool but also a very bloated software for a personal blog. Running such a software requires multiple application with different dependencies, continuous updates and more resources on the system to serve the whole content. Creating additional backups of the docroot and the database require additional time and efforts. All of this is not really necessary when the content is more or less static and comments are deactivated or not used. A flat file approach provides the optional possibility to run and keep everything in git. Generated HTML pages can easily be served even on low resource systems. While this way of blogging mostly targets tech-enthusiasts that are already working on Unix-like systems the idea was to provide a blog engine in a layout and theming of a Unix-like `man page` (manual page). Man pages always align to the same formatting based on `troff` which make man pages look always the same. While man pages provide information of a cli command the idea was to adapt this to a blog. A blog also provides information and especially when serving tech related content it makes much sense to provide it in a similar way. This is the story of how `manpageblog` was born. 167 | 168 | ## License 169 | `manpageblog` 170 | This is free and open source software. You can use, copy, modify, 171 | merge, publish, distribute, sublicense, and/or sell copies of it, 172 | under the terms of the [MIT License](LICENSE.md). 173 | 174 | This software is provided "AS IS", WITHOUT WARRANTY OF ANY KIND, 175 | express or implied. See the [MIT License](LICENSE.md) for details. 176 | 177 | This repository contains the source code of an example website 178 | containing two static blogs and a few static pages. The website can be 179 | generated by running [manpageblog](manpageblog). That's it! 180 | 181 | So go ahead, fork this repository, replace the [content](content) with 182 | your own, and generate your static website. It's that simple! 183 | 184 | You are [free](LICENSE.md) to copy, use, and modify this project for 185 | your blog or website, so go ahead and fork this repository and make it 186 | your own project. Change the [layout](layout) if you wish to, improve 187 | the [stylesheet](static/css/style.css) to suit your taste, enhance 188 | [manpageblog](manpageblog) if you need to, and develop your website/blog 189 | just the way you want it. 190 | -------------------------------------------------------------------------------- /_assets/css/dark.css: -------------------------------------------------------------------------------- 1 | /* Theme: Dark */ 2 | :root { 3 | --main-text-color: #d3d3d3; 4 | --main-bg-color: #000; 5 | --links-color: #d3d3d3; 6 | } 7 | 8 | a:link, a:visited, 9 | a:hover, a:active { text-decoration: underline dotted !important; } 10 | -------------------------------------------------------------------------------- /_assets/css/grey.css: -------------------------------------------------------------------------------- 1 | /* Theme: Grey */ 2 | :root { 3 | --main-text-color: #d3d3d3; 4 | --main-bg-color: #3d3d3d; 5 | --links-color: #d3d3d3; 6 | } 7 | 8 | a:link, a:visited, 9 | a:hover, a:active { text-decoration: underline dotted !important; } 10 | -------------------------------------------------------------------------------- /_assets/css/grey_blue.css: -------------------------------------------------------------------------------- 1 | /* Theme: Grey Blue */ 2 | :root { 3 | --main-text-color: #6082b6; 4 | --main-bg-color: #3d3d3d; 5 | --links-color: #6082b6; 6 | } 7 | 8 | a:link, a:visited, 9 | a:hover, a:active { text-decoration: underline dotted !important; } 10 | -------------------------------------------------------------------------------- /_assets/css/light.css: -------------------------------------------------------------------------------- 1 | /* Theme: Light (default theme) */ 2 | :root { 3 | --main-text-color: #333; 4 | --main-bg-color: #fff; 5 | --links-color: #6d6d6d; 6 | } 7 | -------------------------------------------------------------------------------- /_assets/css/light_blue.css: -------------------------------------------------------------------------------- 1 | /* Theme: Light Blue */ 2 | :root { 3 | --main-text-color: #333; 4 | --main-bg-color: whitesmoke; /* #f5f5f5 */ 5 | --links-color: cornflowerblue; /* #6495ed */ 6 | } 7 | -------------------------------------------------------------------------------- /_assets/css/manpageblog.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Default CSS file for: manpageblog 3 | * Fallback values: Light (default theme) 4 | */ 5 | body { 6 | font: 300 normal 14px/1.25em monospace; 7 | font-family: Menlo, 'DejaVu Sans Mono', Consolas, 'Liberation Mono', monospace; 8 | color: var(--main-text-color, #333); 9 | background: var(--main-bg-color, #fff); 10 | } 11 | 12 | a:link, a:visited { 13 | color: var(--links-color, #6d6d6d); 14 | text-decoration: none; 15 | } 16 | 17 | a:hover, a:active { text-decoration: underline; } 18 | 19 | a, b, strong { font-weight: 600; } 20 | 21 | img { max-width: 100%; height: auto; } 22 | 23 | header section, footer section, manpage { 24 | max-width: 40em; 25 | margin-left: 0%; 26 | } 27 | 28 | main, nav section, name section { 29 | max-width: 60em; 30 | margin-left: 5%; 31 | margin-right: auto; 32 | padding: 0 0.5em; 33 | } 34 | 35 | code { 36 | font-style: italic; 37 | max-width: 60em; 38 | margin-left: 10%; 39 | margin-right: auto; 40 | padding: 0 0.5em; 41 | } 42 | -------------------------------------------------------------------------------- /_templates/feed.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {{ title }} 6 | {{ site_url }}/ 7 | {{ description }} 8 | 9 | {{ logo_site }} 10 | {{ title }} 11 | {{ site_url }}/ 12 | 13 | 14 | {{ content }} 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /_templates/item.html: -------------------------------------------------------------------------------- 1 |
2 | {{ title }} ({{ date }}):
3 | {{ summary }} .... [read more] 4 |
5 |
6 | -------------------------------------------------------------------------------- /_templates/item.xml: -------------------------------------------------------------------------------- 1 | 2 | {{ title }} 3 | {{ site_url }}/{{ blog }}/{{ slug }}/ 4 | {{ site_url }}/{{ blog }}/{{ slug }}/ 5 | 6 | 8 | {{ summary }} ... 9 |

10 |

Read More

11 | ]]> 12 |
13 | {{ rfc_2822_date }} 14 |
15 | -------------------------------------------------------------------------------- /_templates/list.html: -------------------------------------------------------------------------------- 1 | {{ title }} 2 |

3 | {{ content }} 4 | -------------------------------------------------------------------------------- /_templates/page.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{ title }} | {{ subtitle }} 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | NAME
35 |
36 | 37 | 38 |
39 | 40 | {{ name }} 41 | 42 |
43 |
44 | 45 | 46 |
OPTIONS
47 |
48 | 49 | 50 | 60 | 61 | 62 |
CONTENT
63 |
64 | 65 |
66 | {{ content }} 67 |
68 | 69 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /_templates/page_tags.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{ title }} | {{ subtitle }} 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | NAME
34 |
35 | 36 | 37 |
38 | 39 | {{ name }} 40 | 41 |
42 |
43 | 44 | 45 |
OPTIONS
46 |
47 | 48 | 49 | 59 | 60 | 61 |
CONTENT
62 |
63 | 64 |
65 | {{ content }} 66 |
67 | 68 | 69 |
TAGS
70 |
71 | 72 |
73 | {{ keywords }} 74 |
75 | 76 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /_templates/post.html: -------------------------------------------------------------------------------- 1 |
2 | {{ title }} ({{ date }}):
3 | {{ content }} 4 |
5 | -------------------------------------------------------------------------------- /blog.conf: -------------------------------------------------------------------------------- 1 | [general] 2 | name: manpageblog 3 | description: This is the blog of manpageblog where you can find more information. 4 | keywords: blog, minimal, minimalism, manpageblog, pythonblog, blogengine, simple 5 | keywords_show: meta 6 | robots: index,follow 7 | subtitle: manpageblog - a small and lightweight blog engine. 8 | author: admin 9 | copyright: manpageblog 10 | preview_words: 150 11 | logo_site: https://cdn.gyptazy.ch/images/manpageblog.jpg 12 | logo_favicon: https://cdn.gyptazy.ch/images/manpageblog.jpg 13 | logo_apple_touch: https://cdn.gyptazy.ch/images/manpageblog.jpg 14 | 15 | [social] 16 | mastodon: https://mastodon.bsd.cafe/@manpageblog 17 | twitter: @manpageblog 18 | github: manpageblog 19 | 20 | [opengraph] 21 | image_width: 800 22 | image_height: 375 23 | 24 | [processing] 25 | site_url: http://localhost:8000 26 | base_path: 27 | assets: _assets 28 | template_path: _templates 29 | output_path: docroot 30 | output_from_scratch: force 31 | theme: light 32 | -------------------------------------------------------------------------------- /content/_index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Welcome 6 |

7 | Hey and welcome to manpageblog - a small, lightweight blog 8 | engine written in Python and offers several advantages in a look of a man page 9 | (Unix like manual page). 10 | Firstly, it provides simplicity and ease of use, making it accessible even for 11 | users with limited technical knowledge. The lightweight nature ensures quick 12 | installation and minimal resource consumption, making it suitable for various 13 | hosting environments. 14 |

15 | 16 |

17 | Python's readability and straightforward syntax make the blog engine easy to 18 | customize and extend, allowing users to tailor it to their specific needs. 19 | Additionally, being Python-based means leveraging a vast ecosystem of libraries 20 | and frameworks, enhancing the blog's functionality without unnecessary complexity. 21 |

22 | 23 |

24 | The lightweight nature also contributes to faster loading times, improving user 25 | experience and search engine rankings. Overall, a small, lightweight blog engine 26 | in Python combines simplicity, flexibility, and efficiency, making it an ideal 27 | choice for those prioritizing a streamlined and customizable blogging experience. 28 |

29 | 30 |

31 | manpageblog is fully open-source. You can download manpageblog and the code on GitHub:
32 | manpageblog @github 33 |

34 | -------------------------------------------------------------------------------- /content/about.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | About 5 |

6 | Like probably the most ones I started with Wordpress which is a pretty cool but also a very bloated software for a personal blog. 7 | Running such a software requires multiple application with different dependencies, continuous updates and more resources on the 8 | system to serve the whole content. Creating additional backups of the docroot and the database require additional time and efforts. 9 | All of this is not really necessary when the content is more or less static and comments are deactivated or not used. A flat file 10 | approach provides the optional possibility to run and keep everything in git. Generated HTML pages can easily be served even on 11 | low resource systems. While this way of blogging mostly targets tech-enthusiasts that are already working on Unix-like systems the 12 | idea was to provide a blog engine in a layout and theming of a Unix-like `man page` (manual page). Man pages always align to the 13 | same formatting based on troff which make man pages look always the same. While man pages provide information of a cli command 14 | the idea was to adapt this to a blog. A blog also provides information and especially when serving tech related content it makes 15 | much sense to provide it in a similar way. This is the story of how manpageblog was born. 16 |

17 | -------------------------------------------------------------------------------- /content/blog/2023-11-11-manpageblog-release-1-0.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | manpageblog finally got its first release. With version 6 | 1.0 a public release is now present. A small, lightweight blog engine written in Python and offers several advantages 7 | in a look of a man page (Unix like manual page). Firstly, it provides simplicity and ease of use, making it accessible even for users with limited technical knowledge. The lightweight nature ensures quick installation and minimal resource consumption, making it suitable for various hosting environments. No database is needed at all. 8 | Firstly, it provides simplicity and ease of use, making it accessible even for users with limited technical knowledge. 9 | The lightweight nature ensures quick installation and minimal resource consumption, making it suitable for various hosting environments. 10 |

11 | Python's readability and straightforward syntax make the blog engine easy to customize and extend, allowing users 12 | to tailor it to their specific needs. Additionally, being Python-based means leveraging a vast ecosystem of libraries 13 | and frameworks, enhancing the blog's functionality without unnecessary complexity. 14 |

15 | The lightweight nature also contributes to faster loading times, improving user experience and search engine rankings. 16 | Overall, a small, lightweight blog engine in Python combines simplicity, flexibility, and efficiency, making it an 17 | ideal choice for those prioritizing a streamlined and customizable blogging experience. 18 | 19 | Of course, manpageblog also supports regular html tags and code markers which makes it ideal to use for DevOps and developers. 20 |

21 | 22 | 23 | 24 | 25 | 26 | 27 |

28 | Now, you can start blogging. More information can be found on manpageblog.
29 | Download: manpageblog 30 | -------------------------------------------------------------------------------- /content/blog/2023-11-13-manpageblog-now-available-in-freebsd-ports.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | manpageblog can now also be installed by the FreeBSD Ports. 6 | Thanks to Stefan E. for pushing manpageblog to the ports. 7 |

8 | FreeBSD Ports is a system for managing and installing software packages on FreeBSD, a Unix-like operating system. The Ports 9 | Collection is a set of makefiles and scripts that simplify the process of compiling and installing third-party software on FreeBSD. 10 | -------------------------------------------------------------------------------- /content/blog/2023-11-15-manpageblog-release-1-1.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | manpageblog just got released in version 1.1 Version 1.1 comes along with 6 | several bug fixes and some new features.

7 | 8 | Features
9 | * Open Graph support (for sharing on social media paltforms)
10 | * Logo support in RSS feed
11 |
12 | Fixes
13 | * Validate if option are set from config
14 | * Dynamic word-wrap limit now works
15 | * Adjusted documentation
16 | 17 |
18 | Now, you can start blogging. More information can be found on manpageblog.
19 | Download: manpageblog 20 | -------------------------------------------------------------------------------- /content/blog/2023-11-21-manpageblog-in-the-1-mb-website-club.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | manpageblog is now part of the 1MB Club, a collection of performance-focused web pages. 6 | The 1MB Club is a growing collection of performance-focused web pages weighing less than 1 megabyte. Therefore, the goal 7 | is to get back to slim and performant but also content rich web pages again.

8 | 9 | About the 1MB Club
10 | The internet has become a bloated mess. Massive JavaScript libraries. Countless client-side queries. Overly complex frontend frameworks. 11 | But we can make a difference - no matter how small it may seem. 1MB Club is a growing collection of performance-focused web pages found across the internet. All member websites weigh less than 1 megabyte in page size. 12 | -------------------------------------------------------------------------------- /content/blog/2023-11-22-manpageblog-release-1-2.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | manpageblog just got released in version 1.2 Version 1.2 comes along with 6 | several bug fixes and some new features.

7 | 8 | Features
9 | * Add Twitter card support
10 | * Add dynamic favicon support
11 | * Add apple-touch favicon support
12 | * Add grey-scale theme
13 |
14 | Fixes
15 | * Fixed missing language type in html element
16 | 17 |
18 | Now, you can start blogging. More information can be found on manpageblog.
19 | Download: manpageblog 20 | -------------------------------------------------------------------------------- /content/blog/2023-12-15-manpageblock-container-image-for-docker-podman.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | manpageblog can now also be tested in a Container image which is supported by Docker, Podman, etc. 6 | This allows people do test manpageblog without any other dependencies before switching. The Dockerfile can also be found within the GitHub project. 7 |

8 | Resources:
9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 |
Name Version  Container Image Preview Source
manpageblog 1.2  cnt-reg.gyptazy.ch/gyptazy/manpageblog:1.2 manpageblog GitHub
25 | -------------------------------------------------------------------------------- /content/blog/2024-01-09-manpageblog-release-1-3.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | manpageblog just got released in version 1.3 Version 1.3 comes along with 7 | several bug fixes and some new features.

8 | 9 | Features
10 | * Add meta keyword support
11 | * Add tag support
12 | * Add robot support
13 | * Add blue/grey theme
14 |
15 | Fixes
16 | * Fixed rendering issue
17 | 18 |
19 | Now, you can start blogging. More information can be found on manpageblog.
20 | Download: manpageblog 21 | -------------------------------------------------------------------------------- /content/blog/2024-01-14-manpageblog-release-1-3-1.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | manpageblog just got released in version 1.3.1 Version 1.3.1 comes along with 7 | a bug fixe regarding the RSS feed.

8 | 9 | Fixes
10 | * Fixed missing xmlns rss atom feed
11 | * Fixed missing atomic url in each element
12 | 13 |
14 | Now, you can start blogging. More information can be found on manpageblog.
15 | Download: manpageblog 16 | -------------------------------------------------------------------------------- /content/blog/2024-06-06-manpageblog-release-1.4.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | manpageblog just got released in version 1.4. Version 1.4 comes along with several improvements in layout and displaying the content. Please note, that the old commonmark library is deprecated and got replaced by markdown_it.

7 | 8 | Added
9 | * Add link tag for RSS feed
10 |
11 | 12 | Fixes
13 | * Mobile website layout
14 | * Optimized retro browser support
15 | * Replace commonmark (deprecated) with markdown_it
16 | * CSS and font improvements
17 |
18 | 19 | Thanks to Eric (@iefdev) and Pratham (@thefossguy) for their contributions to make manpageblog better! As always, you can find the latest release on GitHub: 20 |
21 | Download: manpageblog 1.4 -------------------------------------------------------------------------------- /content/contact.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Contact 5 |

6 | If you encounter any bugs feel free to raise an issue. You may also contribute to the project (the sources are available on GitHub) 7 | or just download the release for your own usage. Below, you can find all needed links:

8 | Links:
9 | Source: manpageblog source @github
10 | Issue Tracker: manpageblog issues @github
11 | Releases: manpageblog releases @github
12 |

13 | -------------------------------------------------------------------------------- /manpageblog: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright (c) 2023 Florian Paul Azim Hoberg @gyptazy 4 | # All rights reserved 5 | # 6 | # This software is a derivative of the original makesite.py. 7 | # The license text of the original makesite.py is included below. 8 | # The MIT License (MIT) 9 | # 10 | # Copyright (c) 2018-2022 Sunaina Pai 11 | # 12 | # Permission is hereby granted, free of charge, to any person obtaining 13 | # a copy of this software and associated documentation files (the 14 | # "Software"), to deal in the Software without restriction, including 15 | # without limitation the rights to use, copy, modify, merge, publish, 16 | # distribute, sublicense, and/or sell copies of the Software, and to 17 | # permit persons to whom the Software is furnished to do so, subject to 18 | # the following conditions: 19 | # 20 | # The above copyright notice and this permission notice shall be 21 | # included in all copies or substantial portions of the Software. 22 | # 23 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 26 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 27 | # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 28 | # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 29 | # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 30 | 31 | 32 | import argparse 33 | import configparser 34 | import datetime 35 | import glob 36 | import json 37 | import os 38 | import re 39 | import sys 40 | import shutil 41 | import sys 42 | 43 | 44 | def parse_arguments(): 45 | """ Parse arguments by cli input """ 46 | args_parser = argparse.ArgumentParser(description='manpageblog', usage='%(prog)s') 47 | args_parser.add_argument('-c', '--config', default='blog.conf', type=str, help='Path to manpageblog config file.', required=False) 48 | return args_parser.parse_args() 49 | 50 | 51 | def parse_config(config_file): 52 | """ Parse config file for manpageblog """ 53 | try: 54 | config = configparser.ConfigParser() 55 | config.read(config_file) 56 | return config 57 | except configparser.ParsingError: 58 | log('Error parsing config file: Impossible to parse file.') 59 | sys.exit(2) 60 | except KeyError: 61 | log('Error parsing config file: Key/Value not found.') 62 | sys.exit(2) 63 | 64 | 65 | def validate(config): 66 | """ Validate config file for mandatory options """ 67 | log_error = False 68 | 69 | if len(config['general']['name']) == 0: 70 | log('Error: Mandatory field "name" missing.') 71 | log_error = True 72 | 73 | if len(config['general']['description']) == 0: 74 | log('Error: Mandatory field "description" missing.') 75 | log_error = True 76 | 77 | if len(config['general']['subtitle']) == 0: 78 | log('Error: Mandatory field "subtitle" missing.') 79 | log_error = True 80 | 81 | if len(config['processing']['site_url']) == 0: 82 | log('Error: Mandatory field "site_url" missing.') 83 | log_error = True 84 | 85 | if len(config['processing']['assets']) == 0: 86 | log('Error: Mandatory field "assets" missing.') 87 | log_error = True 88 | 89 | if len(config['processing']['template_path']) == 0: 90 | log('Error: Mandatory field "template_path" missing.') 91 | log_error = True 92 | 93 | if len(config['processing']['output_path']) == 0: 94 | log('Error: Mandatory field "output_path" missing.') 95 | log_error = True 96 | 97 | if log_error: 98 | sys.exit(1) 99 | 100 | 101 | def fread(file_name): 102 | """ Read file and close the file """ 103 | with open(file_name, 'r') as f: 104 | return f.read() 105 | 106 | 107 | def fwrite(file_name, text): 108 | """ Write content to file and close the file """ 109 | basedir = os.path.dirname(file_name) 110 | if not os.path.isdir(basedir): 111 | os.makedirs(basedir) 112 | 113 | with open(file_name, 'w') as f: 114 | f.write(text) 115 | 116 | 117 | def log(msg, *args): 118 | """ Log message with specified arguments """ 119 | sys.stderr.write(msg.format(*args) + '\n') 120 | 121 | 122 | def truncate(text, words): 123 | """ Remove tags and truncate text to the specified number of words """ 124 | return ' '.join(re.sub('(?s)<.*?>', ' ', text).split()[:words]) 125 | 126 | 127 | def read_headers(text): 128 | """ Parse headers in text and yield (key, value, end-index) tuples """ 129 | for match in re.finditer(r'\s*\s*|.+', text): 130 | if not match.group(1): 131 | break 132 | yield match.group(1), match.group(2), match.end() 133 | 134 | 135 | def rfc_2822_format(date_str): 136 | """ Convert yyyy-mm-dd date string to RFC 2822 format date string """ 137 | d = datetime.datetime.strptime(date_str, '%Y-%m-%d') 138 | return d.strftime('%a, %d %b %Y %H:%M:%S +0000') 139 | 140 | 141 | def read_content(filename): 142 | """ Read content and metadata from file into a dictionary """ 143 | text = fread(filename) 144 | 145 | # Read metadata and save it in a dictionary. 146 | date_slug = os.path.basename(filename).split('.')[0] 147 | match = re.search(r'^(?:(\d\d\d\d-\d\d-\d\d)-)?(.+)$', date_slug) 148 | content = { 149 | 'date': match.group(1) or '1970-01-01', 150 | 'slug': match.group(2), 151 | } 152 | 153 | # Read headers. 154 | end = 0 155 | for key, val, end in read_headers(text): 156 | content[key] = val 157 | 158 | # Separate content from headers. 159 | text = text[end:] 160 | 161 | # Convert Markdown content to HTML. 162 | if filename.endswith(('.md', '.mkd', '.mkdn', '.mdown', '.markdown')): 163 | try: 164 | from markdown_it import MarkdownIt 165 | md = MarkdownIt() 166 | text = md.render(text) 167 | except ImportError as error: 168 | log('WARNING: Cannot render Markdown in {}: {}', filename, str(error)) 169 | 170 | # Update the dictionary with content and RFC 2822 date. 171 | content.update({ 172 | 'content': text, 173 | 'rfc_2822_date': rfc_2822_format(content['date']) 174 | }) 175 | 176 | return content 177 | 178 | 179 | def render(template, **params): 180 | """ Replace placeholders in template with values from params """ 181 | return re.sub(r'{{\s*([^}\s]+)\s*}}', 182 | lambda match: str(params.get(match.group(1), match.group(0))), 183 | template) 184 | 185 | 186 | def make_pages(src, dst, layout, **params): 187 | """ Generate pages from page content """ 188 | items = [] 189 | 190 | for src_path in glob.glob(src): 191 | content = read_content(src_path) 192 | 193 | page_params = dict(params, **content) 194 | 195 | # Populate placeholders in content if content-rendering is enabled. 196 | if page_params.get('render') == 'yes': 197 | rendered_content = render(page_params['content'], **page_params) 198 | page_params['content'] = rendered_content 199 | content['content'] = rendered_content 200 | 201 | items.append(content) 202 | 203 | dst_path = render(dst, **page_params) 204 | output = render(layout, **page_params) 205 | 206 | log('Rendering {} => {} ...', src_path, dst_path) 207 | fwrite(dst_path, output) 208 | 209 | return sorted(items, key=lambda x: x['date'], reverse=True) 210 | 211 | 212 | def make_list(config, posts, dst, list_layout, item_layout, **params): 213 | """ Generate list page for a blog """ 214 | items = [] 215 | 216 | for post in posts: 217 | item_params = dict(params, **post) 218 | item_params['summary'] = truncate(post['content'], int(config['general'].get('preview_words', 150))) 219 | item = render(item_layout, **item_params) 220 | items.append(item) 221 | 222 | params['content'] = ''.join(items) 223 | dst_path = render(dst, **params) 224 | output = render(list_layout, **params) 225 | 226 | log('Rendering list => {} ...', dst_path) 227 | fwrite(dst_path, output) 228 | 229 | 230 | def main(): 231 | """ Run manpageblog """ 232 | arguments = parse_arguments() 233 | config = parse_config(arguments.config) 234 | validate(config) 235 | 236 | # Create a new directory from scratch 237 | # WARNING: If enabled this will remove the whole directory including all files! 238 | # Since parsing a string from ini would always result in true we make an explicit 239 | # check for the word 'force' 240 | if config['processing']['output_from_scratch'] == 'force': 241 | if os.path.isdir(config['processing']['output_path']): 242 | shutil.rmtree(config['processing']['output_path']) 243 | shutil.copytree(config['processing']['assets'], f"{config['processing']['output_path']}/assets") 244 | 245 | # Remap vars from config 246 | params = { 247 | '_version': '1.1', 248 | 'name': config['general']['name'], 249 | 'description': config['general']['description'], 250 | 'keywords': config['general'].get('keywords', 'unknown'), 251 | 'keywords_show': config['general'].get('keywords_show', 'meta'), 252 | 'robots': config['general'].get('robots', 'noindex,nofollow'), 253 | 'subtitle': config['general']['subtitle'], 254 | 'author': config['general'].get('author', 'unknown'), 255 | 'copyright': config['general'].get('copyright', 'manpageblog'), 256 | 'logo_site': config['general'].get('logo_site', ''), 257 | 'logo_favicon': config['general'].get('logo_favicon', ''), 258 | 'logo_apple_touch': config['general'].get('logo_apple_touch', ''), 259 | 'profile_mastodon': config['social'].get('mastodon', 'unknown'), 260 | 'profile_twitter': config['social'].get('twitter', 'unknown'), 261 | 'image_width': config['opengraph'].get('image_width', '800'), 262 | 'image_height': config['opengraph'].get('image_hight', '375'), 263 | 'profile_github': config['social'].get('github', 'unknown'), 264 | 'site_url': config['processing']['site_url'], 265 | 'base_path': config['processing']['base_path'], 266 | 'theme': config['processing'].get('theme', 'light'), 267 | 'current_year': datetime.datetime.now().year 268 | } 269 | 270 | # Load layouts 271 | if params.get('keywords_show') != 'meta': 272 | page_layout = fread(f'{config["processing"]["template_path"]}/page_tags.html') 273 | else: 274 | page_layout = fread(f'{config["processing"]["template_path"]}/page.html') 275 | post_layout = fread(f'{config["processing"]["template_path"]}/post.html') 276 | list_layout = fread(f'{config["processing"]["template_path"]}/list.html') 277 | item_layout = fread(f'{config["processing"]["template_path"]}/item.html') 278 | feed_xml = fread(f'{config["processing"]["template_path"]}/feed.xml') 279 | item_xml = fread(f'{config["processing"]["template_path"]}/item.xml') 280 | 281 | # Combine layouts to form final layouts 282 | post_layout = render(page_layout, content=post_layout) 283 | list_layout = render(page_layout, content=list_layout) 284 | 285 | # Create site pages 286 | make_pages('content/_index.html', config['processing']['output_path']+'/index.html', page_layout, **params) 287 | make_pages('content/[!_]*.html', config['processing']['output_path']+'/{{ slug }}/index.html', page_layout, **params) 288 | 289 | # Create blogs 290 | blog_posts = make_pages('content/blog/*.md', config['processing']['output_path']+'/blog/{{ slug }}/index.html', post_layout, blog='blog', **params) 291 | 292 | # Create blog list pages 293 | make_list(config, blog_posts, config['processing']['output_path']+'/blog/index.html', list_layout, item_layout, blog='blog', title='Blog', **params) 294 | 295 | # Create RSS feeds 296 | make_list(config, blog_posts, config['processing']['output_path']+'/blog/rss.xml', feed_xml, item_xml, blog='blog', title='Blog', **params) 297 | 298 | 299 | if __name__ == '__main__': 300 | main() 301 | --------------------------------------------------------------------------------