-
Notifications
You must be signed in to change notification settings - Fork 4
/
index.html
283 lines (237 loc) · 21.4 KB
/
index.html
1
2
3
4
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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<!--
# This html template file is part of the
# mkaestatic static website generator.
#
# Author: Michael Borinsky
# Github: https://github.com/michibo/mkaestatic
# License: MIT
# Copyright 2016-2022
-->
<meta http-equiv="content-type" content="text/html;charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no, target-densityDpi=device-dpi" />
<meta name="description" content="" />
<meta name="author" content="" />
<meta name="keywords" content="" />
<title>mkaestatic - readme</title>
<link rel="stylesheet" href="static/style.css" />
</head>
<body>
<div class="layout"><div>
<header>
<span class="logo"><a href=index.html>mkaestatic</a></span>
<input id="nav" type="checkbox">
<label for="nav"></label>
<nav>
<ul>
<li><a href="contact.html">Contact</a></li>
<li><a href="example.html">Example</a></li>
<li><a href="readme.html">readme</a></li>
</ul>
</nav>
</header>
<div class="content">
<h1 class="content-subhead">readme</h1>
<h2>1 What is it?</h2>
<p><strong>mkaestatic</strong> is a minimalist static website generator. It is very lightweight and simple, because it merely combines the powerful standard tools <a href="//www.gnu.org/software/make/">make</a>, <a href="//www.python.org/">python</a>, <a href="//en.wikipedia.org/wiki/Markdown">Markdown</a> and <a href="//palletsprojects.com/p/jinja/">Jinja</a>.</p>
<p>As a static website generator <strong>mkaestatic</strong> converts Markdown files (for instance <em>readme.md</em>, <em>about.md</em> and <em>contact.md</em>) into HTML files (for instance <em>readme.html</em>, <em>about.html</em> and <em>contact.html</em>). The Markdown to HTML conversation is controlled by a Jinja HTML template file, a configuration file and options that are integrated in the Markdown files.</p>
<p><strong>mkaestatic</strong> has a simple command line interface that allows rapid local website development and testing. This interface is entirely based on <strong>make</strong> and integrates smoothly with static website hosting services based on ssh or website hosting via <a href="https://pages.github.com/">GitHub Pages</a>.</p>
<h3>Features</h3>
<ul>
<li>Easily extensible <a href="//www.gnu.org/software/make/">make</a> and <a href="//www.python.org/">python</a> based static website generator</li>
<li>Markdown content and Jinja2 HTML templates</li>
<li>Purely relative URLs that means<ul>
<li>Websites can be copied in bulk to arbitrary subdirectories of web servers (for instance ~user/ websites) without any modification in code.</li>
<li>Websites can be accessed locally or remotely without a HTTP server (i.e. using file:// instead of http://)</li>
<li>Websites can just be a git repository hosted for instance via <a href="https://pages.github.com/">GitHub Pages</a></li>
</ul>
</li>
<li>Arbitrary deep subdirectories</li>
<li>Fast build times even for large projects as changes and dependencies are managed by make</li>
<li>Keeps track of static requisites (as for instance static .css and .js files) using make</li>
<li>Can be easily integrated with other content generating tools (such as <a href="//sass-lang.com/">sass</a>) via make</li>
<li>Only about 350 documented lines of python code</li>
</ul>
<h3>Requirements</h3>
<p>To run <strong>mkaestatic</strong> a python3 installation is required. <strong>mkaestatic</strong> additionally requires</p>
<ul>
<li><a href="//mistune.readthedocs.io/">Mistune</a> as its Markdown implementation (Mistune >= 2.0),</li>
<li><a href="//jinja.palletsprojects.com/">Jinja2</a> as a template engine and</li>
<li><a href="//pyyaml.org/">PyYAML</a> to read and write configuration files.</li>
</ul>
<p>The extra python packages can be installed for instance with <em>pip</em></p>
<pre><code>pip install mistune jinja2 pyyaml</code></pre>
<h2>2 Quickstart</h2>
<h3>Preparation</h3>
<p>Either clone, fork or template the <a href="//github.com/michibo/mkaestatic">repository</a> on GitHub or copy the</p>
<ul>
<li>code files <em>mkaestatic.py</em>, <em>Makefile</em> and <em>Pages.mk</em></li>
<li>and the global configuration file <em>Site.yml</em></li>
<li>at least one example Markdown file <em>readme.md</em>, <em>example.md</em>, <em>contact.md</em> and/or <em>index.md</em></li>
</ul>
<h3>Create a HTML template</h3>
<p>To use <strong>mkaestatic</strong> a Jinja HTML template is needed. As a start you can try the one which is contained in this repository <em>_template/default.html</em> and adapt it to your needs. The path to the template file must either be given in the global <em>Site.yml</em> configuration file or in each .md file individually.</p>
<h3>Create Markdown files</h3>
<p>The next step is to create actual website content using Markdown (.md) files. This repository contains the example Markdown files,</p>
<ul>
<li>readme.md (this file)</li>
<li>example.md (an example with a referenced image)</li>
<li>index.md (mirrors the readme.md file)</li>
<li>contact.md (another example)</li>
<li>other pages (i.e. .md files) in the blog directory to illustrate how subdirectories work
which should illustrate most of the functionality of <strong>mkaestatic</strong>.</li>
</ul>
<h3>Test your website locally and deploy it</h3>
<p>To test the resulting website you can call</p>
<pre><code>make serve</code></pre>
<p>This command converts all .md files into HTML files using <strong>mkaestatic</strong> and starts a local webserver with which the result can be tested. The command line output indicates how you can access the website in your browser. To immediately see something in the browser when the local webserver is accessed, you need to create an <em>index.md</em> file that will be compiled to an <em>index.html</em> file.</p>
<p>The other <strong>mkaestatic</strong> commands are</p>
<pre><code>make</code></pre>
<p>which converts (compiles) the .md files to HTML files,</p>
<pre><code>make clean</code></pre>
<p>which deletes all temporary files (including .html files that were generated),</p>
<pre><code>make build</code></pre>
<p>which copies all the deployment files into a <em>built</em> folder. This folder contains all the necessary files to serve the website and no other files,</p>
<pre><code>make tar</code></pre>
<p>which creates a tar archive <em>built.tar.gz</em> with the complete website and no other files,</p>
<pre><code>make upload</code></pre>
<p>which uploads the complete website to a folder via ssh (the ssh server information must be set in the <em>Makefile</em> for this to work).</p>
<pre><code>make git-add-requisites</code></pre>
<p>which adds all the files that are needed to serve the website to the local git repository. This command is especially useful in combination with <a href="https://pages.github.com/">GitHub Pages</a> or a similar service.</p>
<h2>3 Basic features</h2>
<h3>Local URLs and requisites</h3>
<h4>Local URLs in Markdown files</h4>
<p>The Markdown (.md) files can include hyperlinks to other pages (i.e. other .md/.html files) using the usual Markdown syntax. For instance,</p>
<pre><code>Hello this is a line of Markdown code that refers to the [readme](/readme.html) page.</code></pre>
<p>will produce the text with a link to the <em>readme.html</em> file. The <em>readme.html</em> file can either be an externally provided file or a file which is also generated by <strong>mkaestatic</strong> from <em>readme.md</em>. The hyperlink is translated to a <em>local relatively referenced</em> link in the HTML-code.</p>
<p>You can also included links to static objects this way,</p>
<pre><code>Here you can download a [fancy pdf file](/static/fancy.pdf).</code></pre>
<p>which generates a link to the static PDF-file <em>static/fancy.pdf</em>. <strong>mkaestatic</strong> will produce an error if the file <em>static/fancy.pdf</em> does not exist. If it exists it will be included as a <strong>requisite</strong>. That means it is included in the set of all files that need to be deployed. It is copied together with the all the generated html files into the built folder or uploaded into an ssh server. Local URLs referenced in a Markdown file will always be correctly translated and included into the <strong>make</strong> dependency tree if they start with a slash as in the preceding to examples. The leading slash stands for the top-level directory of your <strong>mkaestatic</strong> workspace directory (i.e. the directory which contains the <em>Makefile</em>).</p>
<h4>Local URLs in Jinja templates</h4>
<p>To reference local pages (local .md/.html file pairs) in template files the Jinja filter <strong>localurl</strong>, which is provided by <strong>mkaestatic</strong>, must be used to translate the URL to the proper relative URL. For instance,</p>
<pre><code><a href="{{ p.url | localurl }}">A link to the page p</a></code></pre>
<p>will translate the URL of the page p (i.e. a local .md/.html file pair) accordingly.</p>
<p>The <strong>localurl</strong> filter must also be used when accessing static local files. For instance,</p>
<pre><code><link rel="stylesheet" href="{{ '/static/css/style.css' | localurl }}"></code></pre>
<p>will translate the local URL '/static/css/style.css' to the respective relative URL which is valid from the currently rendered page and it will add the file <em>/static/css/style.css</em> as a requisite and to the make dependency tree.
This way other tools such as <a href="//sass-lang.com/">sass</a> can be used to compile the .css file from some source by including a respective rule to the <em>Makefile</em>. As in the Markdown files, local URLs used in this way must start with a slash to indicate the reference to the root directory of the <strong>mkaestatic</strong> instance.</p>
<h4>Using actual relative URLs (discouraged)</h4>
<p>If you actually want to specify a relative URL (for instance from a subdirectory) do not use the leading slash. The URL will be resolved with respect to the directory the current <em>page</em> (not the template!).</p>
<h4>Additional static requisites</h4>
<p>Additional requisites that might not be referenced by any website can be included in the header of the <em>Makefile</em> in the configuration variable <strong>REQUISITES</strong>. For instance,</p>
<pre><code>REQUISITES:= robots.txt .htaccess</code></pre>
<p>also includes the files <em>robots.txt</em> and <em>.htaccess</em> which are neither referenced in any Markdown file nor in a template via <strong>localurl</strong>.</p>
<h3>Configuration of pages</h3>
<h4>Local attributes (per page)</h4>
<p>Every Markdown file can have a three dash separated header (as in <a href="https://jekyllrb.com/">Jekyll</a>), where attributes can be defined. These attributes can be accessed from the Jinja HTML template. For instance,</p>
<pre><code>---
title : My frontpage
date : 01.01.1979
template : _templates/frontpage.html
---
*content here* </code></pre>
<p>The Jinja template can now access the attributes using the variables <strong>page.title</strong>, <strong>page.date</strong> and <strong>page.template</strong>.</p>
<p>The <strong>template</strong> attribute has a special role as it sets the <em>Jinja HTML template</em> which will be used to render the HTML file from the Markdown file. A template must be given either in the source file of the page or in the global <em>Site.yml</em> configuration file where a default template for all pages can be specified.</p>
<h4>Global attributes (per site, i.e. one per mkaestatic instance)</h4>
<p>Global attributes can be set in the global <em>Site.yml</em> configuration file. For example,</p>
<pre><code>name : "mkaestatic"
tagline : "is awesome"
template : _templates/default.html</code></pre>
<p>will for instance set the global <strong>name</strong>, <strong>tagline</strong> and <strong>template</strong> attributes. These attributes can be accessed in all templates via the variables <strong>site.name</strong>, <strong>site.tagline</strong>, <strong>site.template</strong>.</p>
<p>The global <strong>template</strong> attribute in <em>Site.yml</em> again has a special role as it can be used to specify a <em>default template</em> for all Markdown files.</p>
<h4>Accessing page configurations in Jinja templates</h4>
<p>The most important variable which is passed from mkaestatic to the Jinja template is the <strong>content</strong> variable. It contains the HTML-code which was rendered from the Markdown input. For instance you can add</p>
<pre><code><div>{{ content }}</div></code></pre>
<p>in the middle of your template for the Markdown content to actually be rendered.</p>
<h4>Local and strictly global attributes</h4>
<p>All attributes can be accessed in the Jinja template with the <strong>page</strong>, <strong>site</strong> or <strong>root</strong> variables. For instance, <strong>page.title</strong> or <strong>page.date</strong> will refer to the values given in the Markdown header that was given as an example above.</p>
<p>Your Jinja template might contain the following line for the <strong>title</strong> tag side the HTML header:</p>
<pre><code><title>{{ site.name|e }} - {{ page.title|e }}</title></code></pre>
<p>The value of <strong>site.name</strong>, the one defined in <em>Site.yml</em>, is similar for all pages in the <em>mkaestatic</em> instance, whereas <strong>page.title</strong> will differ from page to page depending on the definition of <strong>title</strong> in the page header.</p>
<p>The Jinja filter |e escapes special characters in the variables to HTML.</p>
<h4>Special attributes</h4>
<p>Every page has three special attributes which are set internally by <em>mkaestatic</em>: <strong>name</strong>, <strong>url</strong> and <strong>title</strong>. The attribute <strong>name</strong> is the basename of the filename of the Markdown (.md) file. <strong>url</strong> is the URL which can be used to reference the resulting HTML-file. <strong>title</strong> is the same as <strong>name</strong> by default, but can be overwritten in the local configuration.</p>
<p>Optionally, the attribute <strong>mirror</strong> can be set in the local configuration of a page. <strong>mirror</strong> must be set to the filename of another page, whose content will be merely copied to the HTML of the page. This can be useful to deal with compatibility in respect to old url schemes.</p>
<p>Let's say for example that <em>index.html</em> shall have the same content as <em>readme.html</em>:</p>
<p>index.md:</p>
<pre><code>---
mirror: readme.HTML
nomenu: true
---</code></pre>
<h4>Accessing attributes via the directory tree</h4>
<p>With the <strong>site</strong> and <strong>page</strong> variables, global attributes or the attributes of the <em>current Markdown page</em>, which is about to be rendered to HTML, may be accessed. But in many cases the attributes of other pages are also needed. If for instance a menu shall be rendered on the website, the Jinja template needs to know certain attributes, as the title or date, of a bunch of source files.</p>
<p><em>mkaestatic</em> provides a simple data structure for these situations:</p>
<p>In the Jinja template the variable <strong>root</strong> can be accessed. This variable mirrors the structure of the top-level directory (the one in which <strong>make</strong> is invoked and which contains the <em>Makefile</em>) in the <strong>mkaestatic</strong> directory tree. The <strong>root</strong> variable is iterable. If we loop over <strong>root</strong>, we iterate over the configurations of the pages in the top-level directory. For instance,</p>
<pre><code>{% for p in root if not p.nomenu %}
<li class="nav-item">
<a href="{{ p.url | localurl }}">{{ p.title|e }}</a>
</li>
{% endfor %}</code></pre>
<p>will render a menu item for every page (i.e. .md file) in the top-level directory, which was added in the top-level <em>Pages.mk</em>. The page will only be included if the local configuration of the page does not contain a <strong>nomenu</strong> attribute, because of the</p>
<pre><code>if not p.nomenu </code></pre>
<p>filter in the for-loop.</p>
<p>Every page has the additional attribute <strong>url</strong>, which contains the relative url of the page from the top-level directory. As in the line</p>
<pre><code><a href="{{ p.url | localurl }}">{{ p.title|e }}</a></code></pre>
<p>of the example above, the | localurl filter must be added to obtain a relative url which works for pages also in subdirectories (see "Special attributes").</p>
<p>The pages of <em>subdirectories</em> can be iterated over by accessing the respective attributes of <strong>root</strong>. For instance,</p>
<pre><code>{% for p in root.blog %}
...
{% endfor %}</code></pre>
<p>will loop over all pages inside the <em>blog/</em> subdirectory. Such a complete subdirectory example is contained in the <em>Pages.mk</em> of this repository. For a working illustration you have to uncomment the respective section in the SUBDIRECTORIES part of <em>Pages.mk</em> (see also the next section).</p>
<h2>4 Advanced features and further details</h2>
<h3>Under The Hood</h3>
<p><strong>mkaestatics</strong> non-recursive make approach is based Emile van Bergen's article <a href="//evbergen.home.xs4all.nl/nonrecursive-make.html">Implementing non-recursive make</a> which is itself based on the paper <a href="//aegis.sourceforge.net/auug97.pdf">Recursive Make Considered Harmful</a>.</p>
<h3>Pages.mk files in detail</h3>
<p>In <em>Pages.mk</em> the <em>pages</em> and <em>subdirectories</em> of the root directory can be configured. The file is quite long, but most of it is just recursive make management.</p>
<p>By default all .md files in the directory are included as pages in the ordinary <em>Pages.mk</em> file. The filenames of the <em>page</em>-files can also be added one-by-one to the <em>Pages.mk</em> file.
To do so comment out or delete the line</p>
<pre><code>PAGES_SRC_$(d):=$(wildcard $(d)*.md)</code></pre>
<p>in the <em>Pages.mk</em> file. The make variable <em>PAGES_SRC_$(d)</em> must be set to the list of <em>pages</em>. For instance you can add use the line</p>
<pre><code>PAGES_SRC_$(d):=$(d)index.md $(d)readme.md</code></pre>
<p>instead.
A page is a Markdown file with a .md suffix, which will eventually be compiled to a HTML-file. A prefix <strong>$(d)</strong> needs to be added filename. This adds the name of the current directory before the path of <em>page</em> in accordance to non-recursive make practice. The line needs to be inserted into <em>Pages.mk</em> in the following place:</p>
<pre><code>... non recursive make stuff ...
#########################################
# LOCAL PAGES
#########################################
...
PAGES_SRC_$(d):=$(d)index.md $(d)readme.md
# Include the $(d) for reference to the local directory.
# This is the famous non-recursive-make trick!
... more non recursive make stuff ...</code></pre>
<p>Two files are added as target for your project: <em>index.html</em> and <em>readme.html</em>, which will be generated from the Markdown files <em>index.md</em> and <em>readme.md</em> respectively.</p>
<h3>Websites with subdirectories</h3>
<p>To add subdirectories to the <strong>mkaestatic</strong> tree you need to modify (or uncomment) the following section of <em>Pages.mk</em>:</p>
<pre><code>#########################################
# SUBDIRECTORIES
#########################################
# Load config and pages from blog/
dir := $(d)blog/
include $(dir)Pages.mk
MKCONFIGS+=$(dir)Pages.mk
# Load more subdirectories ...
#dir := $(d)blog2/
#include $(dir)Pages.mk
#MKCONFIGS+=$(dir)Pages.mk
#...</code></pre>
<p>Uncommenting these lines in the present repository produces an example with a working subdirectory.</p>
<p>The subdirectories can be added in arbitrary order. Each subdirectory needs to contain its own <em>Pages.mk</em> file of the same form as above. You can add a subdirectory by adding the following lines:</p>
<pre><code>dir := $(d)blog/
include $(dir)Pages.mk
MKCONFIGS+=$(dir)Pages.mk</code></pre>
<p>where the folder <em>blog/</em> is replaced by the respective subdirectory. Note, that you need to include the <strong>$(d)</strong> again before the directory name. In the subdirectory you can add additional <em>pages</em> or <em>subdirectories</em> recursively by modifying the <em>Pages.mk</em> files inside them appropriately.</p>
<h3>ssh-server upload</h3>
<p>You can use <em>mkaestatic</em> to upload your static website to a server via ssh. The necessary ssh-info must be set in the <em>Makefile</em>:</p>
<pre><code>SSH_SERVER := me@myserver.com
SSH_FOLDER := public_html</code></pre>
<p>The command</p>
<pre><code>make upload</code></pre>
<p>will upload all the generated HTML files and all requisites of the page, which are in the dependency tree of make, to the server and put them into the <em>~/$SSH_FOLDER/</em> of the current user. Links in Markdown code and links which are filtered with the <em>localurl</em> Jinja will be automatically included in the upload.</p>
<p>If some static file is missing maybe you missed a | localurl filter in some template or a leading slash for a 'absolute' path.</p>
</div>
</div></div>
</body>
</html>