summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrian Kummerlaender2017-02-11 22:22:27 +0100
committerAdrian Kummerlaender2017-02-11 22:22:27 +0100
commit490963c1550efffe046179ced9b39573185e3e1d (patch)
treea5d7ed4bd1dc7408a77dda09b22ae0d332938925
downloadtree.kummerlaender.eu-490963c1550efffe046179ced9b39573185e3e1d.tar
tree.kummerlaender.eu-490963c1550efffe046179ced9b39573185e3e1d.tar.gz
tree.kummerlaender.eu-490963c1550efffe046179ced9b39573185e3e1d.tar.bz2
tree.kummerlaender.eu-490963c1550efffe046179ced9b39573185e3e1d.tar.lz
tree.kummerlaender.eu-490963c1550efffe046179ced9b39573185e3e1d.tar.xz
tree.kummerlaender.eu-490963c1550efffe046179ced9b39573185e3e1d.tar.zst
tree.kummerlaender.eu-490963c1550efffe046179ced9b39573185e3e1d.zip
Initial implementation of a tree-like website generator based on InputXSLT
The foundation was forked from `blog.kummerlaender.eu`. Currently generates arbitrarily nested markdown documents in addition to overview pages for branches in the tree. This includes resolution of branch node contents.
-rw-r--r--make.xml11
-rw-r--r--source/01_raw/tree.xsl51
-rw-r--r--source/02_data/branches.xsl84
-rw-r--r--source/02_data/leaves.xsl34
-rw-r--r--source/03_meta/meta.xsl29
-rw-r--r--source/99_result/branches.xsl61
-rw-r--r--source/99_result/leaves.xsl37
-rw-r--r--source/99_result/main.css73
-rw-r--r--source/99_result/media/favicon.icobin0 -> 1150 bytes
-rw-r--r--utility/datasource.xsl24
-rw-r--r--utility/date-time.xsl241
-rw-r--r--utility/formatter.xsl134
-rw-r--r--utility/master.xsl76
-rw-r--r--utility/xhtml.xsl28
14 files changed, 883 insertions, 0 deletions
diff --git a/make.xml b/make.xml
new file mode 100644
index 0000000..89637dc
--- /dev/null
+++ b/make.xml
@@ -0,0 +1,11 @@
+<task type="module">
+ <input mode="embedded">
+ <datasource>
+ <meta>
+ <source>source</source>
+ <target>target</target>
+ </meta>
+ </datasource>
+ </input>
+ <definition mode="file">[StaticXSLT.xml]</definition>
+</task>
diff --git a/source/01_raw/tree.xsl b/source/01_raw/tree.xsl
new file mode 100644
index 0000000..f54157b
--- /dev/null
+++ b/source/01_raw/tree.xsl
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet
+ version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:xalan="http://xml.apache.org/xalan"
+ xmlns:InputXSLT="function.inputxslt.application"
+ exclude-result-prefixes="xalan InputXSLT"
+>
+
+<xsl:include href="[utility/formatter.xsl]"/>
+<xsl:include href="[utility/datasource.xsl]"/>
+
+<xsl:variable name="meta">
+ <datasource type="main" mode="xpath" source="$source_tree/directory[@name = '00_content']/directory" target="files"/>
+ <target mode="plain" value="tree.xml"/>
+</xsl:variable>
+
+<xsl:template match="@*|node()" mode="tree">
+ <xsl:copy>
+ <xsl:apply-templates select="@*|node()"/>
+ </xsl:copy>
+</xsl:template>
+
+<xsl:template match="file[@extension = '.md']" mode="tree">
+ <xsl:variable name="content">
+ <xsl:call-template name="formatter">
+ <xsl:with-param name="source" select="InputXSLT:read-file(./full)/text()"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <leaf name="{@name}">
+ <title>
+ <xsl:value-of select="xalan:nodeset($content)/h1"/>
+ </title>
+ <content>
+ <xsl:copy-of select="xalan:nodeset($content)/*[name() != 'h1']"/>
+ </content>
+ </leaf>
+</xsl:template>
+
+<xsl:template match="directory" mode="tree">
+ <branch name="{@name}">
+ <xsl:apply-templates select="node()" mode="tree"/>
+ </branch>
+</xsl:template>
+
+<xsl:template match="files/directory[@name = 'tree']">
+ <xsl:apply-templates select="node()" mode="tree"/>
+</xsl:template>
+
+</xsl:stylesheet>
diff --git a/source/02_data/branches.xsl b/source/02_data/branches.xsl
new file mode 100644
index 0000000..ce661cc
--- /dev/null
+++ b/source/02_data/branches.xsl
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet
+ version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:xalan="http://xml.apache.org/xalan"
+ xmlns:InputXSLT="function.inputxslt.application"
+ exclude-result-prefixes="xalan InputXSLT"
+>
+
+<xsl:include href="[utility/datasource.xsl]"/>
+
+<xsl:variable name="meta">
+ <datasource type="main" mode="full" source="01_raw/tree.xml" target="tree"/>
+ <target mode="plain" value="branches.xml"/>
+</xsl:variable>
+
+<xsl:template match="branch | leaf" mode="serialize">
+ <xsl:apply-templates select="parent::branch" mode="serialize"/>
+ <xsl:text>/</xsl:text>
+ <xsl:value-of select="@name"/>
+</xsl:template>
+
+<xsl:template match="@*|node()" mode="include">
+ <xsl:copy>
+ <xsl:apply-templates select="@*|node()" mode="include"/>
+ </xsl:copy>
+</xsl:template>
+
+<xsl:template match="leaf" mode="include">
+ <xsl:apply-templates select="node()" mode="include"/>
+</xsl:template>
+
+<xsl:template match="leaf" mode="digest">
+ <node name="{@name}">
+ <title>
+ <xsl:value-of select="title"/>
+ </title>
+ <digest size="{string-length(content/p[normalize-space(.)][1])}">
+ <xsl:copy-of select="content/p[normalize-space(.)][1]/node()"/>
+ </digest>
+ </node>
+</xsl:template>
+
+<xsl:template match="leaf">
+ <xsl:variable name="name" select="@name"/>
+
+ <xsl:if test="not(preceding-sibling::branch[@name = $name])">
+ <xsl:apply-templates select="." mode="digest"/>
+ </xsl:if>
+</xsl:template>
+
+<xsl:template match="branch" mode="digest">
+ <xsl:variable name="name" select="@name"/>
+
+ <xsl:apply-templates select="following-sibling::leaf[@name = $name]" mode="digest"/>
+</xsl:template>
+
+<xsl:template match="branch">
+ <xsl:variable name="path">
+ <xsl:apply-templates select="." mode="serialize"/>
+ </xsl:variable>
+
+ <entry handle="{$path}">
+ <xsl:variable name="name" select="@name"/>
+
+ <payload>
+ <xsl:apply-templates select="following-sibling::leaf[@name = $name]" mode="include"/>
+ </payload>
+
+ <branches>
+ <xsl:apply-templates select="branch" mode="digest"/>
+ </branches>
+
+ <leaves>
+ <xsl:apply-templates select="leaf"/>
+ </leaves>
+ </entry>
+</xsl:template>
+
+<xsl:template match="tree">
+ <xsl:apply-templates select="//branch"/>
+</xsl:template>
+
+</xsl:stylesheet>
diff --git a/source/02_data/leaves.xsl b/source/02_data/leaves.xsl
new file mode 100644
index 0000000..81ba8f3
--- /dev/null
+++ b/source/02_data/leaves.xsl
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet
+ version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:xalan="http://xml.apache.org/xalan"
+ xmlns:InputXSLT="function.inputxslt.application"
+ exclude-result-prefixes="xalan InputXSLT"
+>
+
+<xsl:include href="[utility/datasource.xsl]"/>
+
+<xsl:variable name="meta">
+ <datasource type="main" mode="full" source="01_raw/tree.xml" target="tree"/>
+ <target mode="plain" value="leaves.xml"/>
+</xsl:variable>
+
+<xsl:template match="branch | leaf" mode="serialize">
+ <xsl:apply-templates select="parent::branch" mode="serialize"/>
+ <xsl:text>/</xsl:text>
+ <xsl:value-of select="@name"/>
+</xsl:template>
+
+<xsl:template match="tree//leaf[not(preceding-sibling::branch[@name = current()/@name])]">
+ <xsl:variable name="path">
+ <xsl:apply-templates select="." mode="serialize"/>
+ </xsl:variable>
+
+ <entry handle="{$path}">
+ <xsl:copy-of select="title"/>
+ <xsl:copy-of select="content"/>
+ </entry>
+</xsl:template>
+
+</xsl:stylesheet>
diff --git a/source/03_meta/meta.xsl b/source/03_meta/meta.xsl
new file mode 100644
index 0000000..c2bd107
--- /dev/null
+++ b/source/03_meta/meta.xsl
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet
+ version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+>
+
+<xsl:include href="[utility/datasource.xsl]"/>
+
+<xsl:variable name="meta">
+ <datasource type="main" mode="full" source="00_content/meta.xml" target="meta"/>
+ <datasource type="support" mode="full" source="02_data/leaves.xml" target="leaves"/>
+ <target mode="plain" value="meta.xml"/>
+</xsl:variable>
+
+<xsl:template match="meta">
+ <xsl:copy-of select="*"/>
+</xsl:template>
+
+<xsl:template match="leaves/entry">
+ <entry handle="{@handle}"/>
+</xsl:template>
+
+<xsl:template match="leaves">
+ <leaves>
+ <xsl:apply-templates select="entry"/>
+ </leaves>
+</xsl:template>
+
+</xsl:stylesheet>
diff --git a/source/99_result/branches.xsl b/source/99_result/branches.xsl
new file mode 100644
index 0000000..86467ef
--- /dev/null
+++ b/source/99_result/branches.xsl
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet
+ version="1.0"
+ xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:xalan="http://xml.apache.org/xalan"
+ exclude-result-prefixes="xalan"
+>
+
+<xsl:include href="[utility/master.xsl]"/>
+<xsl:include href="[utility/xhtml.xsl]"/>
+
+<xsl:variable name="meta">
+ <datasource type="main" mode="iterate" source="02_data/branches.xml" target="branch"/>
+ <datasource type="support" mode="full" source="03_meta/meta.xml" target="meta"/>
+ <target mode="xpath" value="concat($datasource/branch/entry/@handle, '/index.html')"/>
+</xsl:variable>
+
+<xsl:template name="title-text">
+ <xsl:value-of select="/datasource/branch/entry/@handle"/>
+</xsl:template>
+
+<xsl:template match="branch/entry">
+ <div class="article">
+ <h2>
+ <xsl:text>» </xsl:text>
+ <a href="{@handle}">
+ <xsl:value-of select="payload/title"/>
+ </a>
+ </h2>
+ <p class="info"/>
+
+ <xsl:apply-templates select="payload/content/node()" mode="xhtml"/>
+ </div>
+
+ <div class="columns">
+ <ul class="prettylist">
+ <xsl:apply-templates select="branches/node">
+ <xsl:sort select="digest/@size" data-type="number" order="descending"/>
+ </xsl:apply-templates>
+
+ <xsl:apply-templates select="leaves/node">
+ <xsl:sort select="digest/@size" data-type="number" order="descending"/>
+ </xsl:apply-templates>
+ </ul>
+ </div>
+</xsl:template>
+
+<xsl:template match="entry/*/node">
+ <li>
+ <em>»</em>
+ <a href="{@name}/index.html">
+ <strong><xsl:value-of select="title"/></strong>
+ <p>
+ <xsl:apply-templates select="digest/node()" mode="xhtml"/>
+ </p>
+ </a>
+ </li>
+</xsl:template>
+
+</xsl:stylesheet>
diff --git a/source/99_result/leaves.xsl b/source/99_result/leaves.xsl
new file mode 100644
index 0000000..3f22aa1
--- /dev/null
+++ b/source/99_result/leaves.xsl
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet
+ version="1.0"
+ xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:xalan="http://xml.apache.org/xalan"
+ exclude-result-prefixes="xalan"
+>
+
+<xsl:include href="[utility/master.xsl]"/>
+<xsl:include href="[utility/xhtml.xsl]"/>
+
+<xsl:variable name="meta">
+ <datasource type="main" mode="iterate" source="02_data/leaves.xml" target="leaf"/>
+ <datasource type="support" mode="full" source="03_meta/meta.xml" target="meta"/>
+ <target mode="xpath" value="concat($datasource/leaf/entry/@handle, '/index.html')"/>
+</xsl:variable>
+
+<xsl:template name="title-text">
+ <xsl:value-of select="/datasource/leaf/entry/@handle"/>
+</xsl:template>
+
+<xsl:template match="leaf/entry">
+ <div class="article">
+ <h2>
+ <xsl:text>» </xsl:text>
+ <a href="{@handle}">
+ <xsl:value-of select="title"/>
+ </a>
+ </h2>
+ <p class="info"/>
+
+ <xsl:apply-templates select="content/node()" mode="xhtml"/>
+ </div>
+</xsl:template>
+
+</xsl:stylesheet>
diff --git a/source/99_result/main.css b/source/99_result/main.css
new file mode 100644
index 0000000..ec95157
--- /dev/null
+++ b/source/99_result/main.css
@@ -0,0 +1,73 @@
+body{margin:0;padding:0;font:1em sans-serif;color:#272828;word-wrap:break-word}
+a, a:visited{text-decoration:underline;color:#272828}
+a:hover{color:black}
+h1, h2{margin:0;color:#272828;font-weight:bold}
+h1 a, h2 a{text-decoration:none}
+p{margin:0 0 .5em 0;text-align:justify;line-height:1.75em}
+ul{margin:0;padding:0;list-style:none}
+blockquote{border-left:.4em solid #e3e8e8;margin-left:0;padding-left:1em}
+pre{font-family:monospace;padding:1em;border-radius:.75em;color:#f8f8f2;background:#272822;white-space:pre-wrap}
+code{font-family:monospace;margin:0 .1em;padding:0 .5em;border:.1em solid #e3e8e8;background-color:#f8f8f8;border-radius:.3em}
+.full{width:100%}
+.center{width:45em;margin:0 auto;overflow:hidden}
+.border_bottom{border-bottom:.3em solid #e3e8e8}
+.border_top{border-top:.3em solid #e3e8e8}
+#navigation{padding:2em 0 0 0}
+#navigation h1{font-size:1.1em;line-height:1.5em;font-weight:bold;float:left;padding:0 .2em 0 0;margin:0}
+#navigation ul{float:right;font-size:1.1em}
+#content p{margin-bottom:.7em;text-align:justify}
+#content h2{font-size:1.4em;margin:0;color:#F80}
+#content h2 a, h2 span{font-size:.8em;text-decoration:none !important;color:#272828;font-weight:normal;display:inline-block;vertical-align:middle;max-width:95%}
+#content h2 a:hover{text-decoration:underline !important}
+#content h3, #content h4{font-size:1.05em;font-weight:normal;padding-bottom:.2em;margin:.8em 0 .5em 0;border-bottom:.1em solid #e3e8e8}
+#content .article{border-bottom:.3em dotted #e3e8e8;padding-bottom:.5em;margin-top:1em;text-align:justify}
+#content .article:last-child{border:none}
+#content .article a{text-decoration:underline;color:#272828}
+#content .article a:hover{color:black}
+#content .article ul{float:none;margin-left:2em;text-align:left}
+#content .article ul li{list-style-type:circle;float:none}
+#content .article ul li a{background:0}
+#content .article .info{font-size:.9em;margin-bottom:.5em;margin-left:1.4em}
+#content .article .info a{text-decoration:none;color:#272828}
+#content .article .info a:hover{text-decoration:underline}
+#content .article table{border-collapse:collapse;border-left:.4em solid #e3e8e8;margin:1em}
+#content .article table thead{border-bottom:.1em solid #272828}
+#content .article table tr{border-bottom:.1em solid #272828}
+#content .article table tr:last-child{border-bottom:0}
+#content .article table tr th{font-weight:normal;padding:.2em 1em}
+#content .article table tr td{padding:.2em 1em}
+#content .footnotes {border-top:.3em dotted #e3e8e8}
+#content img{padding:.2em;border:.1em solid #e3e8e8;display:block;margin-left:auto;margin-right:auto;max-width:95%}
+#content img.clear{border:0;max-width:100%}
+#content p.math{padding:0.5em;line-height:0;text-align:center}
+#content span.math{line-height:0}
+#footer{padding-top:.3em}
+#footer a{text-decoration:none;color:#272828}
+#footer a:hover{text-decoration:underline}
+#footer ul{float:right;padding:0}
+.columns{column-count:2;-moz-column-count:2;-webkit-column-count:2;column-gap:1em;-moz-column-gap:1em;-webkit-column-gap:1em}
+.column{-webkit-column-break-inside:avoid;break-inside:avoid-column;overflow:hidden}
+.buttonlist{overflow:hidden}
+.buttonlist li{float:left;background:#e3e8e8;border-radius:.3em;padding:.2em;margin:0 0 .2em .2em}
+.buttonlist li a{text-decoration:none;color:#272828;}
+.buttonlist li a:hover{text-decoration:underline}
+.prettylist li{display:inline-block;padding:.5em 0}
+.prettylist li a{margin-left:.2em;color:#272828;text-decoration:none}
+.prettylist li a:hover{text-decoration:underline}
+.prettylist li p{margin:0 !important}
+.prettylist li em{font-style:normal;font-size:1.4em;color:#F80}
+.prettylist li p em{font-style:italic;color:#272828;font-size:1em}
+.menuhead{border-bottom:0.1em solid #e3e8e8;overflow:hidden;padding:0;margin-top:0.8em}
+.menuhead h3{float:left;padding:0.4em 0 0 0;margin:0 !important;border:none !important}
+.menuhead ul{float:right;padding:0;font-size:1.1em}
+@media screen and (max-width:46em){
+ #content .article h2 a{max-width:90%}
+ #navigation{padding:.3em 0 0 0}
+ .center{width:98%}
+ .columns{column-count:1;-moz-column-count:1;-webkit-column-count:1}
+ .column{width:100%}
+}
+@media screen and (max-width:30em){
+ #navigation h1{float:none}
+ #navigation ul{float:none}
+}
diff --git a/source/99_result/media/favicon.ico b/source/99_result/media/favicon.ico
new file mode 100644
index 0000000..f5a9ac4
--- /dev/null
+++ b/source/99_result/media/favicon.ico
Binary files differ
diff --git a/utility/datasource.xsl b/utility/datasource.xsl
new file mode 100644
index 0000000..411086a
--- /dev/null
+++ b/utility/datasource.xsl
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet
+ version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+>
+
+<xsl:output
+ method="xml"
+ omit-xml-declaration="no"
+ encoding="UTF-8"
+ indent="no"
+/>
+
+<xsl:variable name="root" select="/datasource"/>
+
+<xsl:template match="/">
+ <datasource>
+ <xsl:apply-templates />
+ </datasource>
+</xsl:template>
+
+<xsl:template match="text()|@*"/>
+
+</xsl:stylesheet>
diff --git a/utility/date-time.xsl b/utility/date-time.xsl
new file mode 100644
index 0000000..1815e06
--- /dev/null
+++ b/utility/date-time.xsl
@@ -0,0 +1,241 @@
+<?xml version="1.0" encoding="utf-8"?>
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+
+<!--
+
+Description:
+
+This is a date formatting utility. The named template "format-date" takes 2 parameters:
+
+1. date - [required] takes an ISO date (2005-12-01)
+2. format - [optional] takes a format string.
+
+Format options:
+
+Y - year in 4 digits e.g. 1981, 1992, 2008
+y - year in 2 digits e.g. 81, 92, 08
+M - month as a full word e.g. January, March, September
+m - month in 3 letters e.g. Jan, Mar, Sep
+N - month in digits without leading zero
+n - month in digits with leading zero
+D - day with suffix and no leading zero e.g. 1st, 23rd
+d - day in digits with leading zero e.g. 01, 09, 12, 25
+x - day in digits with no leading zero e.g. 1, 9, 12, 25
+T - time in 24-hours e.g. 18:30
+t - time in 12-hours e.g. 6:30pm
+W - weekday as a full word e.g. Monday, Tuesday
+w - weekday in 3 letters e.g. Mon, Tue, Wed
+
+Examples:
+
+M => January
+d M => 21 September
+m D, y => Sep 21st, 81
+n-d-y => 09-21-81
+d/n/y => 21/09/81
+d/n/y t => 21/09/81 6:30pm
+
+-->
+
+<xsl:template name="format-date">
+ <xsl:param name="date"/>
+ <xsl:param name="format" select="'D M, Y'"/>
+ <xsl:choose>
+ <xsl:when test="string-length($format) &lt;= 10">
+ <xsl:call-template name="date-controller">
+ <xsl:with-param name="date" select="$date"/>
+ <xsl:with-param name="format" select="$format"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>Error: format parameter is not correctly set. You have: </xsl:text>
+ <xsl:value-of select="string-length($format)"/>
+ <xsl:text>.</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+<xsl:template name="date-controller">
+ <xsl:param name="date"/>
+ <xsl:param name="format"/>
+ <xsl:param name="letter" select="substring($format,1,1)"/>
+ <xsl:param name="tletter" select="translate($letter,'DMNYTW','dmnytw')"/>
+ <xsl:choose>
+ <xsl:when test="$tletter = 'y'">
+ <xsl:call-template name="format-year">
+ <xsl:with-param name="date" select="$date"/>
+ <xsl:with-param name="format" select="$letter"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$tletter = 'm'">
+ <xsl:call-template name="format-month">
+ <xsl:with-param name="date" select="$date"/>
+ <xsl:with-param name="format" select="$letter"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$tletter = 'n'">
+ <xsl:call-template name="format-month">
+ <xsl:with-param name="date" select="$date"/>
+ <xsl:with-param name="format" select="$letter"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$tletter = 'd'">
+ <xsl:call-template name="format-day">
+ <xsl:with-param name="date" select="$date"/>
+ <xsl:with-param name="format" select="$letter"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$tletter = 'x'">
+ <xsl:call-template name="format-day">
+ <xsl:with-param name="date" select="$date"/>
+ <xsl:with-param name="format" select="$letter"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$tletter = 't'">
+ <xsl:call-template name="format-time">
+ <xsl:with-param name="time" select="$date/@time"/>
+ <xsl:with-param name="format" select="$letter"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$tletter = 'w'">
+ <xsl:call-template name="format-weekday">
+ <xsl:with-param name="weekday" select="$date/@weekday"/>
+ <xsl:with-param name="format" select="$letter"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$letter"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:if test="$letter = not('')">
+ <xsl:call-template name="date-controller">
+ <xsl:with-param name="date" select="$date"/>
+ <xsl:with-param name="format" select="substring($format,2)"/>
+ </xsl:call-template>
+ </xsl:if>
+</xsl:template>
+
+<xsl:template name="format-year">
+ <xsl:param name="date"/>
+ <xsl:param name="year" select="substring($date,1,4)"/>
+ <xsl:param name="format" select="'y'"/>
+ <xsl:choose>
+ <xsl:when test="$format = 'y'">
+ <xsl:value-of select="substring($year,3)"/>
+ </xsl:when>
+ <xsl:when test="$format = 'Y'">
+ <xsl:value-of select="$year"/>
+ </xsl:when>
+ </xsl:choose>
+</xsl:template>
+
+<xsl:template name="format-month">
+ <xsl:param name="date"/>
+ <xsl:param name="month" select="format-number(substring($date,6,2), '##')"/>
+ <xsl:param name="format" select="'m'"/>
+ <xsl:param name="month-word">
+ <xsl:choose>
+ <xsl:when test="$month = 01">January</xsl:when>
+ <xsl:when test="$month = 02">February</xsl:when>
+ <xsl:when test="$month = 03">March</xsl:when>
+ <xsl:when test="$month = 04">April</xsl:when>
+ <xsl:when test="$month = 05">May</xsl:when>
+ <xsl:when test="$month = 06">June</xsl:when>
+ <xsl:when test="$month = 07">July</xsl:when>
+ <xsl:when test="$month = 08">August</xsl:when>
+ <xsl:when test="$month = 09">September</xsl:when>
+ <xsl:when test="$month = 10">October</xsl:when>
+ <xsl:when test="$month = 11">November</xsl:when>
+ <xsl:when test="$month = 12">December</xsl:when>
+ </xsl:choose>
+ </xsl:param>
+ <xsl:choose>
+ <xsl:when test="$format = 'm'">
+ <xsl:value-of select="substring($month-word, 1,3)"/>
+ </xsl:when>
+ <xsl:when test="$format = 'M'">
+ <xsl:value-of select="$month-word"/>
+ </xsl:when>
+ <xsl:when test="$format = 'n'">
+ <xsl:value-of select="format-number($month, '00')"/>
+ </xsl:when>
+ <xsl:when test="$format = 'N'">
+ <xsl:value-of select="format-number($month, '0')"/>
+ </xsl:when>
+ </xsl:choose>
+</xsl:template>
+
+<xsl:template name="format-day">
+ <xsl:param name="date"/>
+ <xsl:param name="day" select="format-number(substring($date,9,2),'00')"/>
+ <xsl:param name="format" select="'d'"/>
+ <xsl:param name="suffix">
+ <xsl:choose>
+ <xsl:when test="(substring($day,2) = 1) and not(substring($day,1,1) = 1)">st</xsl:when>
+ <xsl:when test="(substring($day,2) = 2) and not(substring($day,1,1) = 1)">nd</xsl:when>
+ <xsl:when test="(substring($day,2) = 3) and not(substring($day,1,1) = 1)">rd</xsl:when>
+ <xsl:otherwise>th</xsl:otherwise>
+ </xsl:choose>
+ </xsl:param>
+ <xsl:choose>
+ <xsl:when test="$format = 'd'">
+ <xsl:value-of select="$day"/>
+ </xsl:when>
+ <xsl:when test="$format = 'x'">
+ <xsl:value-of select="format-number($day,'0')"/>
+ </xsl:when>
+ <xsl:when test="$format = 'D'">
+ <xsl:value-of select="format-number($day,'0')"/>
+ <xsl:value-of select="$suffix"/>
+ </xsl:when>
+ </xsl:choose>
+</xsl:template>
+
+<xsl:template name="format-time">
+ <xsl:param name="time"/>
+ <xsl:param name="hour" select="substring-before($time, ':')"/>
+ <xsl:param name="minute" select="substring-after($time, ':')"/>
+ <xsl:param name="format" select="'T'"/>
+ <xsl:choose>
+ <xsl:when test="$format = 'T'">
+ <xsl:value-of select="$time"/>
+ </xsl:when>
+ <xsl:when test="$format = 't'">
+ <xsl:choose>
+ <xsl:when test="$hour mod 12 = 0">12</xsl:when>
+ <xsl:otherwise><xsl:value-of select="($hour mod 12)"/></xsl:otherwise>
+ </xsl:choose>
+ <xsl:value-of select="concat(':',$minute)"/>
+ <xsl:choose>
+ <xsl:when test="$hour &lt; 12">am</xsl:when>
+ <xsl:otherwise>pm</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ </xsl:choose>
+</xsl:template>
+
+<xsl:template name="format-weekday">
+ <xsl:param name="weekday"/>
+ <xsl:param name="format" select="'w'"/>
+ <xsl:param name="result">
+ <xsl:choose>
+ <xsl:when test="$weekday = 1">Monday</xsl:when>
+ <xsl:when test="$weekday = 2">Tuesday</xsl:when>
+ <xsl:when test="$weekday = 3">Wednesday</xsl:when>
+ <xsl:when test="$weekday = 4">Thursday</xsl:when>
+ <xsl:when test="$weekday = 5">Friday</xsl:when>
+ <xsl:when test="$weekday = 6">Saturday</xsl:when>
+ <xsl:when test="$weekday = 7">Sunday</xsl:when>
+ </xsl:choose>
+ </xsl:param>
+ <xsl:choose>
+ <xsl:when test="$format = 'W'">
+ <xsl:value-of select="$result"/>
+ </xsl:when>
+ <xsl:when test="$format = 'w'">
+ <xsl:value-of select="substring($result,1,3)"/>
+ </xsl:when>
+ </xsl:choose>
+</xsl:template>
+
+</xsl:stylesheet> \ No newline at end of file
diff --git a/utility/formatter.xsl b/utility/formatter.xsl
new file mode 100644
index 0000000..f590d89
--- /dev/null
+++ b/utility/formatter.xsl
@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet
+ version="1.0"
+ xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:xalan="http://xml.apache.org/xalan"
+ xmlns:InputXSLT="function.inputxslt.application"
+ exclude-result-prefixes="xalan InputXSLT"
+>
+
+<xsl:template name="plain_formatter">
+ <xsl:param name="format"/>
+ <xsl:param name="source"/>
+
+ <xsl:copy-of select="InputXSLT:external-command(
+ $format,
+ $source
+ )/self::command/node()"/>
+</xsl:template>
+
+<xsl:template name="math_highlighter">
+ <xsl:param name="source"/>
+ <xsl:param name="arguments"/>
+
+ <xsl:variable name="formatted_expression">
+ <xsl:call-template name="plain_formatter">
+ <xsl:with-param name="format">
+ <xsl:text>katex </xsl:text>
+ <xsl:value-of select="$arguments"/>
+ </xsl:with-param>
+ <xsl:with-param name="source" select="$source"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:copy-of select="xalan:nodeset($formatted_expression)/node()"/>
+</xsl:template>
+
+<xsl:template name="code_highlighter">
+ <xsl:param name="source"/>
+ <xsl:param name="language"/>
+
+ <xsl:variable name="formatted_code">
+ <xsl:call-template name="plain_formatter">
+ <xsl:with-param name="format">
+ <xsl:text>highlight --out-format=xhtml --inline-css --style=molokai --fragment --enclose-pre --wrap-simple --syntax=</xsl:text>
+ <xsl:value-of select="$language"/>
+ </xsl:with-param>
+ <xsl:with-param name="source" select="$source"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <pre>
+ <xsl:copy-of select="xalan:nodeset($formatted_code)/pre/node()"/>
+ </pre>
+</xsl:template>
+
+<xsl:template match="@*|node()" mode="embellish">
+ <xsl:copy>
+ <xsl:apply-templates select="@*|node()" mode="embellish"/>
+ </xsl:copy>
+</xsl:template>
+
+<xsl:template match="h2" mode="embellish">
+ <h3>
+ <xsl:apply-templates select="node()" mode="embellish"/>
+ </h3>
+</xsl:template>
+
+<xsl:template match="h3" mode="embellish">
+ <h4>
+ <xsl:apply-templates select="node()" mode="embellish"/>
+ </h4>
+</xsl:template>
+
+<xsl:template match="pre" mode="embellish">
+ <xsl:call-template name="code_highlighter">
+ <xsl:with-param name="source" select="code/text()"/>
+ <xsl:with-param name="language">
+ <xsl:choose>
+ <xsl:when test="@class">
+ <xsl:value-of select="@class"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>txt</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:with-param>
+ </xsl:call-template>
+</xsl:template>
+
+<xsl:template match="div[@class = 'figure']" mode="embellish">
+ <p>
+ <xsl:apply-templates select="img" mode="embellish"/>
+ </p>
+</xsl:template>
+
+<xsl:template match="div[@class = 'footnotes']/hr" mode="embellish"/>
+
+<xsl:template match="span[contains(@class, 'math')]" mode="embellish">
+ <xsl:choose>
+ <xsl:when test="contains(@class, 'display')">
+ <p class="math">
+ <xsl:call-template name="math_highlighter">
+ <xsl:with-param name="source" select="text()"/>
+ <xsl:with-param name="arguments">
+ <xsl:text>--display-mode</xsl:text>
+ </xsl:with-param>
+ </xsl:call-template>
+ </p>
+ </xsl:when>
+ <xsl:otherwise>
+ <span class="math">
+ <xsl:call-template name="math_highlighter">
+ <xsl:with-param name="source" select="text()"/>
+ </xsl:call-template>
+ </span>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:template>
+
+<xsl:template name="formatter">
+ <xsl:param name="source"/>
+
+ <xsl:variable name="content">
+ <xsl:call-template name="plain_formatter">
+ <xsl:with-param name="format">pandoc -f markdown -t html --katex --no-highlight</xsl:with-param>
+ <xsl:with-param name="source" select="$source"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:apply-templates select="xalan:nodeset($content)" mode="embellish"/>
+</xsl:template>
+
+</xsl:stylesheet>
diff --git a/utility/master.xsl b/utility/master.xsl
new file mode 100644
index 0000000..80bfccd
--- /dev/null
+++ b/utility/master.xsl
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet
+ version="1.0"
+ xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+>
+
+<xsl:output
+ method="xml"
+ doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
+ doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
+ omit-xml-declaration="yes"
+ encoding="UTF-8"
+ indent="no"
+/>
+
+<xsl:variable name="root" select="datasource"/>
+
+<xsl:template match="/">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <meta name="author" content="Adrian Kummerländer" />
+ <meta name="robots" content="all"/>
+ <meta name="viewport" content="width=device-width,initial-scale=1.0"/>
+
+ <link rel="stylesheet" type="text/css" href="/main.css" />
+ <link rel="shortcut icon" type="image/x-icon" href="/media/favicon.ico" />
+
+ <xsl:if test="//*[(self::p or self::span) and @class = 'math']">
+ <link rel="stylesheet" type="text/css" href="https://static.kummerlaender.eu/katex/katex.min.css" />
+ </xsl:if>
+
+ <title>
+ <xsl:call-template name="title-text"/> @ <xsl:value-of select="$root/meta/title"/>
+ </title>
+</head>
+<body>
+ <div id="navigation" class="center border_bottom">
+ <h1>
+ <xsl:value-of select="$root/meta/title"/>
+ </h1>
+
+ <ul class="buttonlist">
+ <li>
+ <a href="/">Start</a>
+ </li>
+ <li>
+ <a href="/projects">Projects</a>
+ </li>
+ <li>
+ <a href="/