summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Oberhollenzer <goliath@infraroot.at>2020-03-17 16:10:23 +0100
committerDavid Oberhollenzer <goliath@infraroot.at>2020-06-28 17:18:45 +0200
commitbb34d2b128ebc1b95f7cbd40876689707eb1e1e0 (patch)
tree2262dd6c1332e5526700ecb8e138daca8a1c7bd3
Initial commit
Signed-off-by: David Oberhollenzer <goliath@infraroot.at>
-rw-r--r--.gitignore5
-rw-r--r--img/favicon.pngbin0 -> 1923 bytes
-rw-r--r--img/logo.pngbin0 -> 3170 bytes
-rwxr-xr-xmk.sh115
-rw-r--r--pagecfg.sh4
-rw-r--r--pages/contact.md4
-rw-r--r--pages/impressum.md12
-rw-r--r--pages/index.md21
-rw-r--r--pages/menu.csv5
-rw-r--r--pages/pages.csv4
-rw-r--r--pages/projects.md15
-rw-r--r--pages/projects/squashfs-tools-ng/index.md113
-rw-r--r--pages/projects/squashfs-tools-ng/menu.csv5
-rw-r--r--pages/projects/squashfs-tools-ng/pages.csv1
-rwxr-xr-xrun_lighttpd.sh26
-rw-r--r--templates/menu_active.html1
-rw-r--r--templates/menu_inactive.html1
-rw-r--r--templates/page.html38
-rw-r--r--templates/robots.txt2
-rw-r--r--templates/sitemap.xml6
-rw-r--r--templates/style.css416
-rwxr-xr-xutil/copyright.sh24
-rwxr-xr-xutil/sitemap.sh14
23 files changed, 832 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..575cd98
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+*~
+*.css
+*.html
+*.conf
+*.tar*
diff --git a/img/favicon.png b/img/favicon.png
new file mode 100644
index 0000000..6185a74
--- /dev/null
+++ b/img/favicon.png
Binary files differ
diff --git a/img/logo.png b/img/logo.png
new file mode 100644
index 0000000..61870bf
--- /dev/null
+++ b/img/logo.png
Binary files differ
diff --git a/mk.sh b/mk.sh
new file mode 100755
index 0000000..d46f93c
--- /dev/null
+++ b/mk.sh
@@ -0,0 +1,115 @@
+#!/bin/bash
+
+SCRIPTDIR=$(cd $(dirname "$0") && pwd)
+PAGEDIR="$SCRIPTDIR/pages"
+IMAGEDIR="$SCRIPTDIR/img"
+TEMPLATEDIR="$SCRIPTDIR/templates"
+UTILDIR="$SCRIPTDIR/util"
+SITEMAP="$(pwd)/sitemap.xml"
+
+source "$SCRIPTDIR/pagecfg.sh"
+
+###############################################################################
+
+pagemenu() {
+ local current="$1"
+ local basedir="$(dirname $current)"
+
+ cat "$basedir/menu.csv" | while read line; do
+ local name=$(echo $line | cut -d, -f1)
+ local target=$(echo $line | cut -d, -f2)
+ local template="$TEMPLATEDIR/menu_inactive.html"
+
+ if [[ "$target" =~ ^\./.* ]]; then
+ target=$(echo $target | sed "s#^./#/${basedir}/#g")
+ fi
+
+ if [ "$(basename $target)" == "$(basename $current)" ]; then
+ template="$TEMPLATEDIR/menu_active.html"
+ fi
+
+ if [[ "$target" =~ \.md$ ]]; then
+ target=$(echo $target | sed 's/\.md/.html/g')
+ fi
+
+ sed -e "s#TARGET#$target#g" -e "s#NAME#${name^}#g" "$template"
+ done
+}
+
+generate_page() {
+ local mdpath="$1"
+ local pagename="${2^}"
+ local longtitle="${3^}"
+
+ sed -e "s#LONG_TITLE#$longtitle#g" \
+ -e "s#SHORT_TITLE#$pagename#g" \
+ -e "s#STYLESHEET#/$STYLESHEET#g" \
+ -e "s#FAVICON#/$FAVICON#g" \
+ -e "s#LOGO#/$LOGO#g" \
+ -e "s#URL#$URL#g" "$TEMPLATEDIR/page.html" | \
+ while read pageline; do
+ case "$pageline" in
+ MENU)
+ pagemenu "$mdpath"
+ ;;
+ CONTENT)
+ markdown "$mdpath"
+ ;;
+ COPYRIGHT)
+ "$UTILDIR/copyright.sh" "$mdpath"
+ ;;
+ *)
+ echo "$pageline"
+ ;;
+ esac
+ done
+}
+
+###############################################################################
+
+sitemap_begin() {
+ sed '/ENTRIES/Q' "$TEMPLATEDIR/sitemap.xml"
+}
+
+sitemap_entry() {
+ "$UTILDIR/sitemap.sh" "$URL" "$1" "$2"
+
+}
+
+sitemap_end() {
+ sed -e '1,/ENTRIES/ d' "$TEMPLATEDIR/sitemap.xml"
+}
+
+###############################################################################
+cp "$TEMPLATEDIR/$STYLESHEET" .
+cp -r "$IMAGEDIR" .
+
+sitemap_begin > "$SITEMAP"
+
+find "$PAGEDIR" -name pages.csv -printf "%P\n" |\
+while read cfgfile; do
+ cat "$PAGEDIR/$cfgfile" |\
+ while read line; do
+ mdpath="$(dirname $cfgfile)/$(echo $line | cut -d, -f1)"
+ pagename="$(echo $line | cut -d, -f2)"
+ longtitle="$(echo $line | cut -d, -f3)"
+ htmlpath="$(echo $mdpath | sed 's/\.md/.html/g')"
+ htmlpath_abs="$(pwd)/$htmlpath"
+ abs_link_path=$(echo "$htmlpath" | sed -e 's#^./##' \
+ -e "s#^#/#")
+
+ mkdir -p "$(dirname $htmlpath_abs)"
+
+ pushd "$PAGEDIR" > /dev/null
+ sitemap_entry "$mdpath" "$abs_link_path" >> "$SITEMAP"
+
+ generate_page "$mdpath" "$pagename" "$longtitle" \
+ > "$htmlpath_abs"
+ popd > /dev/null
+ done
+done
+
+sitemap_end >> "$SITEMAP"
+
+cp "$TEMPLATEDIR/robots.txt" .
+echo "Sitemap: ${URL%/}/sitemap.xml" >> "robots.txt"
diff --git a/pagecfg.sh b/pagecfg.sh
new file mode 100644
index 0000000..561666f
--- /dev/null
+++ b/pagecfg.sh
@@ -0,0 +1,4 @@
+FAVICON="img/favicon.png"
+STYLESHEET="style.css"
+LOGO="img/logo.png"
+URL="https://www.infraroot.at/"
diff --git a/pages/contact.md b/pages/contact.md
new file mode 100644
index 0000000..4374f70
--- /dev/null
+++ b/pages/contact.md
@@ -0,0 +1,4 @@
+# Contact
+
+If you feel the need to contact someone regarding any technical/hosting related
+issues, send an e-mail to our [toastmaster](mailto:toastmaster@infraroot.at).
diff --git a/pages/impressum.md b/pages/impressum.md
new file mode 100644
index 0000000..10e74e8
--- /dev/null
+++ b/pages/impressum.md
@@ -0,0 +1,12 @@
+# Impressum
+
+Betreiber/Inhaber dieser Webseite ist (§25, MedienG):
+
+ David Oberhollenzer
+ Fürstenweg 30
+ A-6020 Innsbruck
+ Österreich
+
+## Administrative Anfragen
+
+Email-Adresse: [toastmaster@infraroot.at](mailto:toastmaster@infraroot.at)
diff --git a/pages/index.md b/pages/index.md
new file mode 100644
index 0000000..9368c73
--- /dev/null
+++ b/pages/index.md
@@ -0,0 +1,21 @@
+# About
+
+This place is primarily intended to
+host [free software](https://www.gnu.org/philosophy/free-sw.html) projects.
+
+The name "infraroot" is a German/English word play. _Infrarot_ being the German
+word for _infra red_, with _rot_ meaning _red_ and also being spelled similar
+to _root_. It can also pass as a Dutch word play (_infrarood_) and possibly
+other languages as well.
+
+Infraroot is not a company or other kind of entity and currently run just by
+myself, David Oberhollenzer, as a private individual. Infraroot is also not a
+cult and doesn't have any bullshit philosophy.
+
+There is currently no real content for this main page yet, but the domain and
+web server are already used for hosting some projects.
+
+There already is an official [infraroot Git server](https://git.infraroot.at/)
+running on a sub domain. Also, feel free to browse
+the [pub directory](https://infraroot.at/pub/) for software releases and other
+interesting things.
diff --git a/pages/menu.csv b/pages/menu.csv
new file mode 100644
index 0000000..c5d829b
--- /dev/null
+++ b/pages/menu.csv
@@ -0,0 +1,5 @@
+About,./index.md
+Projects,./projects.md
+Contact,./contact.md
+Impressum,./impressum.md
+Git,https://git.infraroot.at/
diff --git a/pages/pages.csv b/pages/pages.csv
new file mode 100644
index 0000000..434eb8d
--- /dev/null
+++ b/pages/pages.csv
@@ -0,0 +1,4 @@
+index.md,infraroot,about infraroot
+projects.md,infraroot,infraroot projects
+contact.md,infraroot,contact
+impressum.md,infraroot,impressum
diff --git a/pages/projects.md b/pages/projects.md
new file mode 100644
index 0000000..0dc6c32
--- /dev/null
+++ b/pages/projects.md
@@ -0,0 +1,15 @@
+# Projects hosted on infraroot.at
+
+The following projects are currently hosted here:
+
+ - [squashfs-tools-ng](/projects/squashfs-tools-ng/index.html)
+ - Pygos, but there is no descriptive site for it yet.
+
+## Mirrored Projects
+
+The following projects are currently mirrored here:
+
+ - [The pub directory](https://infraroot.at/pub/mtd/) has
+ copies of all releases of [mtd-utils](http://www.linux-mtd.infradead.org/)
+ and the Git repository
+ [is mirrored here as well](https://git.infraroot.at/mtd-utils.git/)
diff --git a/pages/projects/squashfs-tools-ng/index.md b/pages/projects/squashfs-tools-ng/index.md
new file mode 100644
index 0000000..ea81448
--- /dev/null
+++ b/pages/projects/squashfs-tools-ng/index.md
@@ -0,0 +1,113 @@
+# SquashFS Tools NG
+
+SquashFS is a highly compressed, read only file system often used as a root fs
+on embedded devices, live systems or simply as a compressed archive format.
+
+Think of it as a .tar.gz that you can mount (or XZ, LZO, LZ4, ZSTD).
+
+This project originally started out as a fork
+of [squashfs-tools](https://github.com/plougher/squashfs-tools) 4.3, after
+encountering some short comings and realizing that there have been no updates
+on the SourceForge site or mailing list for _years_.
+
+Even before the first public release, the fork was replaced with a complete
+re-write after growing frustrated with the existing code base. For lack of a
+better name, and because the original appeared to be unmaintained at the time,
+the name squashfs-tools-ng was kept, although the published code base
+technically never had any connection to squashfs-tools.
+
+Maintenance of the original squashfs-tools has since resumed, squashfs-tools
+version 4.4 was released and continues to be maintained in parallel. The
+utilities provided by squashfs-tools-ng offer alternative tooling and are
+intentionally named differently, so both packages can be installed side by
+side.
+
+**The actual guts of squashfs-tools-ng are encapsulated in a library
+with a generic API** designed to make SquashFS available to other applications
+as an embeddable, extensible archive format (or to simply read, write or
+manipulate SquashFS file systems).
+
+The utility programs are largely command line wrappers around the library. The
+following tools are provided:
+
+ - `gensquashfs` can be used to produce SquashFS images from `gen_init_cpio`
+ like file listings or simply pack an input directory. Can use an SELinux
+ contexts file (see selabel_file(5)) to generate SELinux labels.
+ - `rdsquashfs` can be used to inspect and unpack SquashFS images.
+ - `sqfs2tar` can turn a SquashFS image into a tarball, written to stdout.
+ - `tar2sqfs` can turn a tarball (read from stdin) into a SquashFS image.
+ - `sqfsdiff` can compare the contents of two SquashFS images.
+
+The library and the tools that produce SquashFS images are designed to operate
+deterministically. Same input will produce byte-for-byte identical output.
+Failure to do so is treated as a critical bug.
+
+## Version history
+
+| Date | Release |
+| ---------- | ------------------------------------------------------------------------------------------------------- |
+| 2020-06-13 | [squashfs-tools-ng 1.0.0 is released](https://infraroot.at/pub/squashfs/squashfs-tools-ng-1.0.0.tar.xz) |
+| 2020-05-03 | [squashfs-tools-ng 0.9.1 is released](https://infraroot.at/pub/squashfs/squashfs-tools-ng-0.9.1.tar.xz) |
+| 2020-03-30 | [squashfs-tools-ng 0.9.0 is released](https://infraroot.at/pub/squashfs/squashfs-tools-ng-0.9.tar.xz) |
+| 2019-12-30 | [squashfs-tools-ng 0.8.0 is released](https://infraroot.at/pub/squashfs/squashfs-tools-ng-0.8.tar.xz) |
+| 2019-10-08 | [squashfs-tools-ng 0.7.0 is released](https://infraroot.at/pub/squashfs/squashfs-tools-ng-0.7.tar.xz) |
+| 2019-08-27 | [squashfs-tools-ng 0.6.1 is released](https://infraroot.at/pub/squashfs/squashfs-tools-ng-0.6.1.tar.xz) |
+| 2019-08-22 | [squashfs-tools-ng 0.6.0 is released](https://infraroot.at/pub/squashfs/squashfs-tools-ng-0.6.tar.xz) |
+| 2019-07-28 | [squashfs-tools-ng 0.5.0 is released](https://infraroot.at/pub/squashfs/squashfs-tools-ng-0.5.tar.xz) |
+| 2019-07-17 | [squashfs-tools-ng 0.4.2 is released](https://infraroot.at/pub/squashfs/squashfs-tools-ng-0.4.2.tar.xz) |
+| 2019-07-07 | [squashfs-tools-ng 0.4.1 is released](https://infraroot.at/pub/squashfs/squashfs-tools-ng-0.4.1.tar.xz) |
+| 2019-07-04 | [squashfs-tools-ng 0.4.0 is released](https://infraroot.at/pub/squashfs/squashfs-tools-ng-0.4.tar.xz) |
+| 2019-06-30 | [squashfs-tools-ng 0.3.0 is released](https://infraroot.at/pub/squashfs/squashfs-tools-ng-0.3.tar.xz) |
+| 2019-06-13 | [squashfs-tools-ng 0.2.0 is released](https://infraroot.at/pub/squashfs/squashfs-tools-ng-0.2.tar.xz) |
+| 2019-06-09 | [squashfs-tools-ng 0.1.0 is released](https://infraroot.at/pub/squashfs/squashfs-tools-ng-0.1.tar.xz) |
+
+## Documentation
+
+The doxygen reference for the current release of libsquashfs is available
+here: [libsquashfs API reference](doxydoc/index.html).
+
+A writeup on the [SquashFS on-disk format](https://git.infraroot.at/squashfs-tools-ng.git/tree/doc/format.txt)
+is also available.
+
+Man pages are provided for the individual tools.
+
+## Getting the Source Code
+
+[Release tar balls](https://infraroot.at/pub/squashfs/) are published in the
+pub directory.
+
+The Git tree is hosted on [git.infraroot.at](https://git.infraroot.at/squashfs-tools-ng.git/)
+as well as on [GitHub](https://github.com/AgentD/squashfs-tools-ng).
+
+Those two Git trees are kept in sync and issues & pull-requests on the GitHub
+pages are accepted.
+
+## Installing
+
+A number of Linux distributions already offer squashfs-tools-ng through
+their package management system. Replogy maintains an up to date list:
+
+[![Packaging status](https://repology.org/badge/vertical-allrepos/squashfs-tools-ng.svg)](https://repology.org/project/squashfs-tools-ng/versions)
+
+Pre-compiled binary packages for Windows are
+available [here](https://infraroot.at/pub/squashfs/windows).
+
+Those packages contain the binaries for the tools, the SquashFS library and
+pre-compiled dependency libraries (zstd, lzo, lzma; others are built in).
+
+The binary package does not contain any source code. The corresponding source
+code from which the 3rd party libraries have been built is also available for
+download at the above location.
+
+The headers and import libraries to build applications that use libsquashfs
+are included. For convenience, the pre-compiled, 3rd party dependency libraries
+also come with headers and import libraries.
+
+## Contact
+
+Besides the issue tracker on GitHub, you can reach me via e-mail as *goliath*
+on *infraroot.at*.
+
+There is currently no official mailing list. For the time being I'll use
+the existing [squashfs-tools mailing list](https://sourceforge.net/p/squashfs/mailman/)
+for announcments, until I'm booted off.
diff --git a/pages/projects/squashfs-tools-ng/menu.csv b/pages/projects/squashfs-tools-ng/menu.csv
new file mode 100644
index 0000000..9a926b0
--- /dev/null
+++ b/pages/projects/squashfs-tools-ng/menu.csv
@@ -0,0 +1,5 @@
+home,/
+about,./index.md
+doxygen,./doxydoc/index.html
+download,https://infraroot.at/pub/squashfs
+git,https://git.infraroot.at/squashfs-tools-ng.git
diff --git a/pages/projects/squashfs-tools-ng/pages.csv b/pages/projects/squashfs-tools-ng/pages.csv
new file mode 100644
index 0000000..018e080
--- /dev/null
+++ b/pages/projects/squashfs-tools-ng/pages.csv
@@ -0,0 +1 @@
+index.md,SquashFS Tools NG,infraroot projects - squashfs tools ng
diff --git a/run_lighttpd.sh b/run_lighttpd.sh
new file mode 100755
index 0000000..0f45714
--- /dev/null
+++ b/run_lighttpd.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+
+LIGHTTPDCONF="lighttpd.conf"
+
+preview_lighttpd_conf() {
+cat <<_EOF
+server.document-root = "$(pwd)"
+server.port = 8080
+
+index-file.names = ( "index.html" )
+
+mimetype.assign = (
+ ".html" => "text/html",
+ ".css" => "text/css",
+ ".jpeg" => "image/jpeg",
+ ".jpg" => "image/jpeg",
+ ".png" => "image/png",
+ ".gif" => "image/gif"
+)
+_EOF
+}
+
+echo "Launching server for preview: http://localhost:8080/"
+
+preview_lighttpd_conf > "$LIGHTTPDCONF"
+lighttpd -D -f "$LIGHTTPDCONF"
diff --git a/templates/menu_active.html b/templates/menu_active.html
new file mode 100644
index 0000000..9f12438
--- /dev/null
+++ b/templates/menu_active.html
@@ -0,0 +1 @@
+<a class="active" href="TARGET">NAME</a>
diff --git a/templates/menu_inactive.html b/templates/menu_inactive.html
new file mode 100644
index 0000000..c340b76
--- /dev/null
+++ b/templates/menu_inactive.html
@@ -0,0 +1 @@
+<a href="TARGET">NAME</a>
diff --git a/templates/page.html b/templates/page.html
new file mode 100644
index 0000000..fe1b847
--- /dev/null
+++ b/templates/page.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+<title>LONG_TITLE</title>
+<link rel="stylesheet" type="text/css" href="STYLESHEET">
+<link rel="shortcut icon" href="FAVICON">
+</head>
+<body>
+<table id="header">
+<tbody>
+<tr>
+<td class="logo" rowspan="2"><a href="URL"><img src="LOGO"/></a></td>
+<td class="title">SHORT_TITLE</td>
+</tr>
+<tr><td class="sub">LONG_TITLE</td></tr>
+</tbody>
+</table>
+<table class="tabs">
+<tbody>
+<tr>
+<td>
+MENU
+</td>
+</tr>
+</tbody>
+</table>
+<div id="main">
+CONTENT
+</div>
+<div class="footer">
+COPYRIGHT
+Page Style derived from <a href="https://git.zx2c4.com/cgit/about/">cgit v1.2.1</a>.
+<br/>
+<a href="/impressum.html">Impressum</a>.
+</div>
+</body>
+</html>
diff --git a/templates/robots.txt b/templates/robots.txt
new file mode 100644
index 0000000..c2a49f4
--- /dev/null
+++ b/templates/robots.txt
@@ -0,0 +1,2 @@
+User-agent: *
+Allow: /
diff --git a/templates/sitemap.xml b/templates/sitemap.xml
new file mode 100644
index 0000000..d49148e
--- /dev/null
+++ b/templates/sitemap.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">
+ENTRIES
+</urlset>
diff --git a/templates/style.css b/templates/style.css
new file mode 100644
index 0000000..a5085db
--- /dev/null
+++ b/templates/style.css
@@ -0,0 +1,416 @@
+body {
+ padding: 0em;
+ margin: 0em;
+ font-family: sans-serif;
+ font-size: 10pt;
+ color: #333;
+ background: white;
+}
+
+a {
+ color: blue;
+ text-decoration: none;
+}
+
+a:hover {
+ text-decoration: underline;
+}
+
+table {
+ border-collapse: collapse;
+}
+
+table#header {
+ width: 100%;
+ margin-bottom: 1em;
+}
+
+table#header td.logo {
+ width: 96px;
+ vertical-align: top;
+}
+
+table#header td.title {
+ font-size: 250%;
+ padding-left: 10px;
+ white-space: nowrap;
+}
+
+table#header td.sub {
+ color: #777;
+ border-top: solid 1px #ccc;
+ padding-left: 10px;
+}
+
+table.tabs {
+ border-bottom: solid 3px #ccc;
+ border-collapse: collapse;
+ margin-top: 2em;
+ margin-bottom: 0px;
+ width: 100%;
+}
+
+table.tabs td {
+ padding: 0px 1em;
+ vertical-align: bottom;
+}
+
+table.tabs td a {
+ padding: 2px 0.75em;
+ color: #777;
+ font-size: 110%;
+}
+
+table.tabs td a.active {
+ color: #000;
+ background-color: #ccc;
+}
+
+div.footer {
+ margin-top: 0.5em;
+ text-align: center;
+ font-size: 80%;
+ color: #777;
+}
+
+div.footer a {
+ color: #777;
+ text-decoration: none;
+}
+
+div.footer a:hover {
+ text-decoration: underline;
+}
+
+div#main {
+ margin: 0px;
+ padding: 2em;
+ border-bottom: solid 3px #ccc;
+ font-size: 14px;
+ line-height: 1.6;
+ overflow: hidden;
+}
+
+div#main>*:first-child {
+ margin-top: 0 !important;
+}
+
+div#main>*:last-child {
+ margin-bottom: 0 !important;
+}
+
+div#main a.absent {
+ color: #c00;
+}
+
+div#main a.anchor {
+ display: block;
+ padding-left: 30px;
+ margin-left: -30px;
+ cursor: pointer;
+ position: absolute;
+ top: 0;
+ left: 0;
+ bottom: 0;
+}
+
+div#main h1, div#main h2, div#main h3, div#main h4, div#main h5, div#main h6 {
+ margin: 20px 0 10px;
+ padding: 0;
+ font-weight: bold;
+ -webkit-font-smoothing: antialiased;
+ cursor: text;
+ position: relative;
+}
+
+div#main h1 .mini-icon-link, div#main h2 .mini-icon-link, div#main h3 div#main, div#main h4 .mini-icon-link, div#main h5 .mini-icon-link, div#main h6 .mini-icon-link {
+ display: none;
+ color: #000;
+}
+
+div#main h1:hover a.anchor, div#main h2:hover a.anchor, div#main h3:hover a.anchor, div#main h4:hover a.anchor, div#main h5:hover a.anchor, div#main h6:hover a.anchor {
+ text-decoration: none;
+ line-height: 1;
+ padding-left: 0;
+ margin-left: -22px;
+ top: 15%
+}
+
+div#main h1:hover a.anchor .mini-icon-link, div#main h2:hover a.anchor .mini-icon-link, div#main h3:hover a.anchor .mini-icon-link, div#main h4:hover a.anchor .mini-icon-link, div#main h5:hover a.anchor .mini-icon-link, div#main h6:hover a.anchor .mini-icon-link {
+ display: inline-block;
+}
+
+div#main h1 tt, div#main h1 code, div#main h2 tt, div#main h2 code, div#main h3 tt, div#main h3 code, div#main h4 tt, div#main h4 code, div#main h5 tt, div#main h5 code, div#main h6 tt, div#main h6 code {
+ font-size: inherit;
+}
+
+div#main h1 {
+ font-size: 28px;
+ color: #000;
+}
+
+div#main h2 {
+ font-size: 24px;
+ border-bottom: 1px solid #ccc;
+ color: #000;
+}
+
+div#main h3 {
+ font-size: 18px;
+}
+
+div#main h4 {
+ font-size: 16px;
+}
+
+div#main h5 {
+ font-size: 14px;
+}
+
+div#main h6 {
+ color: #777;
+ font-size: 14px;
+}
+
+div#main p, div#main blockquote, div#main ul, div#main ol, div#main dl, div#main table, div#main pre {
+ margin: 15px 0;
+}
+
+div#main>h2:first-child, div#main>h1:first-child, div#main>h1:first-child+h2, div#main>h3:first-child, div#main>h4:first-child, div#main>h5:first-child, div#main>h6:first-child {
+ margin-top: 0;
+ padding-top: 0;
+}
+
+div#main a:first-child h1, div#main a:first-child h2, div#main a:first-child h3, div#main a:first-child h4, div#main a:first-child h5, div#main a:first-child h6 {
+ margin-top: 0;
+ padding-top: 0;
+}
+
+div#main h1+p, div#main h2+p, div#main h3+p, div#main h4+p, div#main h5+p, div#main h6+p {
+ margin-top: 0;
+}
+
+div#main li p.first {
+ display: inline-block;
+}
+
+div#main ul, div#main ol {
+ padding-left: 30px;
+}
+
+div#main ul.no-list, div#main ol.no-list {
+ list-style-type: none;
+ padding: 0;
+}
+
+div#main ul li>:first-child, div#main ul li ul:first-of-type, div#main ul li ol:first-of-type, div#main ol li>:first-child, div#main ol li ul:first-of-type, div#main ol li ol:first-of-type {
+ margin-top: 0px;
+}
+
+div#main ul li p:last-of-type, div#main ol li p:last-of-type {
+ margin-bottom: 0;
+}
+
+div#main ul ul, div#main ul ol, div#main ol ol, div#main ol ul {
+ margin-bottom: 0;
+}
+
+div#main dl {
+ padding: 0;
+}
+
+div#main dl dt {
+ font-size: 14px;
+ font-weight: bold;
+ font-style: italic;
+ padding: 0;
+ margin: 15px 0 5px;
+}
+
+div#main dl dt:first-child {
+ padding: 0;
+}
+
+div#main dl dt>:first-child {
+ margin-top: 0px;
+}
+
+div#main dl dt>:last-child {
+ margin-bottom: 0px;
+}
+
+div#main dl dd {
+ margin: 0 0 15px;
+ padding: 0 15px;
+}
+
+div#main dl dd>:first-child {
+ margin-top: 0px;
+}
+
+div#main dl dd>:last-child {
+ margin-bottom: 0px;
+}
+
+div#main blockquote {
+ border-left: 4px solid #DDD;
+ padding: 0 15px;
+ color: #777;
+}
+
+div#main blockquote>:first-child {
+ margin-top: 0px;
+}
+
+div#main blockquote>:last-child {
+ margin-bottom: 0px;
+}
+
+div#main table th {
+ font-weight: bold;
+}
+
+div#main table th, div#main table td {
+ border: 1px solid #ccc;
+ padding: 6px 13px;
+}
+
+div#main table tr {
+ border-top: 1px solid #ccc;
+ background-color: #fff;
+}
+
+div#main table tr:nth-child(2n) {
+ background-color: #f8f8f8;
+}
+
+div#main img {
+ max-width: 100%;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+
+div#main span.frame {
+ display: block;
+ overflow: hidden;
+}
+
+div#main span.frame>span {
+ border: 1px solid #ddd;
+ display: block;
+ float: left;
+ overflow: hidden;
+ margin: 13px 0 0;
+ padding: 7px;
+ width: auto;
+}
+
+div#main span.frame span img {
+ display: block;
+ float: left;
+}
+
+div#main span.frame span span {
+ clear: both;
+ color: #333;
+ display: block;
+ padding: 5px 0 0;
+}
+
+div#main span.align-center {
+ display: block;
+ overflow: hidden;
+ clear: both;
+}
+
+div#main span.align-center>span {
+ display: block;
+ overflow: hidden;
+ margin: 13px auto 0;
+ text-align: center;
+}
+
+div#main span.align-center span img {
+ margin: 0 auto;
+ text-align: center;
+}
+
+div#main span.align-right {
+ display: block;
+ overflow: hidden;
+ clear: both;
+}
+
+div#main span.align-right>span {
+ display: block;
+ overflow: hidden;
+ margin: 13px 0 0;
+ text-align: right;
+}
+
+div#main span.align-right span img {
+ margin: 0;
+ text-align: right;
+}
+
+div#main span.float-left {
+ display: block;
+ margin-right: 13px;
+ overflow: hidden;
+ float: left;
+}
+
+div#main span.float-left span {
+ margin: 13px 0 0;
+}
+
+div#main span.float-right {
+ display: block;
+ margin-left: 13px;
+ overflow: hidden;
+ float: right;
+}
+
+div#main span.float-right>span {
+ display: block;
+ overflow: hidden;
+ margin: 13px auto 0;
+ text-align: right;
+}
+
+div#main code, div#main tt {
+ margin: 0 2px;
+ padding: 0px 5px;
+ border: 1px solid #eaeaea;
+ background-color: #f8f8f8;
+ border-radius: 3px;
+}
+
+div#main code {
+ white-space: nowrap;
+}
+
+div#main pre>code {
+ margin: 0;
+ padding: 0;
+ white-space: pre;
+ border: none;
+ background: transparent;
+}
+
+div#main .highlight pre, div#main pre {
+ background-color: #f8f8f8;
+ border: 1px solid #ccc;
+ font-size: 13px;
+ line-height: 19px;
+ overflow: auto;
+ padding: 6px 10px;
+ border-radius: 3px;
+}
+
+div#main pre code, div#main pre tt {
+ margin: 0;
+ padding: 0;
+ background-color: transparent;
+ border: none;
+}
diff --git a/util/copyright.sh b/util/copyright.sh
new file mode 100755
index 0000000..a21caf9
--- /dev/null
+++ b/util/copyright.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+
+filename="$1"
+
+git log --follow --pretty=format:"%ad,%an" --date="format:%Y" -- "$filename" |\
+awk -F, '{
+ if (length(min[$2]) == 0) {
+ min[$2] = max[$2] = $1
+ } else {
+ max[$2]=$1 > max[$2] ? $1 : max[$2]
+ min[$2]=$1 < min[$2] ? $1 : min[$2]
+ }
+ }END{
+ for (a in max)
+ print a "," min[a] "," max[a]
+ }' |\
+sort --field-separator=',' --key=3 --reverse |\
+awk -F, '{
+ if ($2 == $3) {
+ print "Copyright &copy; " $2 " " $1 "<br/>"
+ } else {
+ print "Copyright &copy; " $2 "-" $3 " " $1 "<br/>"
+ }
+}'
diff --git a/util/sitemap.sh b/util/sitemap.sh
new file mode 100755
index 0000000..643ed44
--- /dev/null
+++ b/util/sitemap.sh
@@ -0,0 +1,14 @@
+#!/bin/bash
+
+url="${1%/}"
+mdpath="$2"
+htmlpath="${3#/}"
+
+date=$(git log -1 --format=%cs "$mdpath")
+
+cat <<_EOF
+<url>
+<loc>$(echo $url/$htmlpath)</loc>
+<lastmod>$date</lastmod>
+</url>
+_EOF