1 Commits

Author SHA1 Message Date
Alex Schroeder
faf9198edd Add sitemap command and handler 2026-01-02 22:30:02 +01:00
21 changed files with 206 additions and 741 deletions

View File

@@ -1,8 +1,7 @@
SHELL=/bin/bash
PREFIX=${HOME}/.local
BINARIES=oddmu-linux-amd64.tar.gz oddmu-linux-arm64.tar.gz oddmu-darwin-amd64.tar.gz oddmu-windows-amd64.tar.gz
.PHONY: help build test run upload docs install priv clean dist dist-upload
.PHONY: help build test run upload docs install priv
help:
@echo Help for Oddmu
@@ -66,10 +65,7 @@ clean:
rm --force oddmu oddmu.exe oddmu-{linux,darwin,windows}-{amd64,arm64}{,.tar.gz}
cd man && make clean
dist-upload: $(BINARIES)
rsync -ai $^ sibirocobombus:alexschroeder.ch/wiki/oddmu/
dist: $(BINARIES)
dist: oddmu-linux-amd64.tar.gz oddmu-linux-arm64.tar.gz oddmu-darwin-amd64.tar.gz oddmu-windows-amd64.tar.gz
oddmu-linux-amd64: *.go
GOOS=linux GOARCH=amd64 go build -o $@

11
feed.go
View File

@@ -16,9 +16,7 @@ import (
type dateSource int
const (
// ModTime means that the feed item date is based on the page file's last modification date.
ModTime dateSource = iota
// URL means that the feed item date is based on the ISO date contained in the page name.
URL
)
@@ -69,12 +67,11 @@ func feed(p *Page, ti time.Time, from, n int, source dateSource) *Feed {
feed.Date = ti.Format(time.RFC1123Z)
feed.From = from
feed.N = n
switch {
case n == 0:
if n == 0 {
feed.Complete = true
case from > n:
} else if from > n {
feed.Prev = from - n
default:
} else {
year, err := p.BlogYear()
if err == nil && p.ArchiveExists(year+1) {
feed.PrevYear = year + 1
@@ -153,7 +150,7 @@ func (p *Page) Date(source dateSource) (time.Time, error) {
return p.ModTime()
}
// BlogYear returns the current year if the page name is "index". If the page name is a number such as "2026" then
// BLogYear returns the current year if the page name is "index". If the page name is a number such as "2026" then
// this is parsed as an integer and returned.
func (p *Page) BlogYear() (int, error) {
name := path.Base(p.Name)

View File

@@ -5,7 +5,7 @@
.nh
.ad l
.\" Begin generated content:
.TH "ODDMU-APACHE" "5" "2026-01-29"
.TH "ODDMU-APACHE" "5" "2025-07-16"
.PP
.SH NAME
.PP
@@ -48,7 +48,7 @@ ServerAdmin alex@alexschroeder\&.ch
<VirtualHost *:443>
ServerName transjovian\&.org
SSLEngine on
ProxyPassMatch "^/((view|preview|diff|edit|save|add|append|upload|drop|search|archive)/(\&.*)|sitemap.xml)?$"
ProxyPassMatch "^/((view|preview|diff|edit|save|add|append|upload|drop|search|archive)/(\&.*))?$"
"http://localhost:8080/$1"
</VirtualHost>
.fi
@@ -126,13 +126,13 @@ ServerAdmin alex@alexschroeder\&.ch
ServerName transjovian\&.org
ProxyPassMatch "^/((view|diff|search|archive)/(\&.*))?$"
"http://localhost:8080/$1"
RedirectMatch "^/((edit|save|add|append|upload|drop)/(\&.*)|sitemap.xml)?$"
RedirectMatch "^/((edit|save|add|append|upload|drop)/(\&.*))?$"
"https://transjovian\&.org/$1"
</VirtualHost>
<VirtualHost *:443>
ServerName transjovian\&.org
SSLEngine on
ProxyPassMatch "^/((view|preview|diff|edit|save|add|append|upload|drop|search|archive)/(\&.*)|sitemap.xml)?$"
ProxyPassMatch "^/((view|preview|diff|edit|save|add|append|upload|drop|search|archive)/(\&.*))?$"
"http://localhost:8080/$1"
</VirtualHost>
.fi
@@ -170,7 +170,7 @@ In that case, you need to use the ProxyPassMatch directive.\&
.PP
.nf
.RS 4
ProxyPassMatch "^/((view|preview|diff|edit|save|add|append|upload|drop|search|archive)/(\&.*)|sitemap.xml)?$"
ProxyPassMatch "^/((view|preview|diff|edit|save|add|append|upload|drop|search|archive)/(\&.*))?$"
"unix:/run/oddmu/oddmu\&.sock|http://localhost/$1"
.fi
.RE
@@ -189,7 +189,7 @@ A workaround is to add the redirect manually and drop the question-mark:
.nf
.RS 4
RedirectMatch "^/$" "/view/index"
ProxyPassMatch "^/((view|preview|diff|edit|save|add|append|upload|drop|search|archive)/(\&.*)|sitemap.xml)$"
ProxyPassMatch "^/((view|preview|diff|edit|save|add|append|upload|drop|search|archive)/(\&.*))$"
"unix:/run/oddmu/oddmu\&.sock|http://localhost/$1"
.fi
.RE
@@ -248,74 +248,12 @@ to your "<VirtualHost *:443>" section:
.fi
.RE
.PP
.SS Actual usernames and passwords for authentication
.PP
On a community server where the users have accounts, wiki editing can be limited
to the system'\&s users.\&
.PP
In order to do this, install the \fBmod-authnz-external\fR module for Apache and the
\fBpwauth\fR binary.\& The module allows the password checking normally done inside
Apache to be done by an separate external program running outside of Apache.\&
.PP
Here'\&s an example configuration:
.PP
.nf
.RS 4
AddExternalAuth pwauth /usr/sbin/pwauth
SetExternalAuthMethod pwauth pipe
<LocationMatch "^/(edit|save|add|append|upload|drop)/">
AuthType Basic
AuthName "Password Required"
AuthBasicProvider external
AuthExternal pwauth
Require valid-user
</LocationMatch>
.fi
.RE
.PP
.SS Different logins for different access rights
.PP
What if you have a site with various subdirectories and each subdirectory is for
a different group of friends?\& You can set this up using your webserver.\& One way
to do this is to require specific usernames (which must have a password in the
password file mentioned above.\&
.PP
This requires a valid login by the user "alex" or "berta":
.PP
.nf
.RS 4
<LocationMatch "^/(edit|save|add|append|upload|drop)/intetebi/">
Require user alex berta
</LocationMatch>
.fi
.RE
.PP
.SS Private wikis
.PP
Based on the above, you can prevent people from \fIreading\fR the wiki.\& The location
must cover all the URLs in order to protect everything.\&
.PP
.nf
.RS 4
<Location />
AuthType Basic
AuthName "Password Required"
AuthUserFile /home/oddmu/\&.htpasswd
Require valid-user
</Location>
.fi
.RE
.PP
.SS Subdirectories as separate sites
.PP
The way Oddmu handles subdirectories is that all files and directories are
visible, except for "hidden" files and directories (whose name starts with a
period).\& Specifically, do not rely on Apache to hide locations in subdirectories
from public view.\& Search reveals the existence of these pages and produces an
extract, even if users cannot follow the links.\& The Sitemap lists all pages,
including subdirectories.\& Archive links pack all the subdirectories, including
locations you may have hidden from view using Apache.\&
extract, even if users cannot follow the links.\& Archive links pack all the
subdirectories, including locations you may have hidden from view using Apache.\&
.PP
If you to treat subdirectories as separate sites, you need to set the
environment variable ODDMU_FILTER to a regular expression matching the those
@@ -400,13 +338,46 @@ In this case, "/css/oddmu-2023.\&css" would be the name of your stylesheet.\& If
your document root is "/home/oddmu", then the filename of your stylesheet would
have to be "/home/oddmu/css/oddmu-2023.\&css" for this to work.\&
.PP
.SS Different logins for different access rights
.PP
What if you have a site with various subdirectories and each subdirectory is for
a different group of friends?\& You can set this up using your webserver.\& One way
to do this is to require specific usernames (which must have a password in the
password file mentioned above.\&
.PP
This requires a valid login by the user "alex" or "berta":
.PP
.nf
.RS 4
<LocationMatch "^/(edit|save|add|append|upload|drop)/intetebi/">
Require user alex berta
</LocationMatch>
.fi
.RE
.PP
.SS Private wikis
.PP
Based on the above, you can prevent people from \fIreading\fR the wiki.\& The location
must cover all the URLs in order to protect everything.\&
.PP
.nf
.RS 4
<Location />
AuthType Basic
AuthName "Password Required"
AuthUserFile /home/oddmu/\&.htpasswd
Require valid-user
</Location>
.fi
.RE
.PP
.SS Virtual hosting
.PP
Virtual hosting in this context means that the program serves two different
sites for two different domains from the same machine.\& Oddmu doesn'\&t support
that, but your webserver does.\& Therefore, start an Oddmu instance for every
domain name, each listening on a different port.\& Then set up your web server
such that every domain proxies for a different Oddmu instance.\&
such that ever domain acts as a reverse proxy to a different Oddmu instance.\&
.PP
.SH SEE ALSO
.PP

View File

@@ -209,61 +209,6 @@ to your "<VirtualHost \*:443>" section:
</LocationMatch>
```
## Actual usernames and passwords for authentication
On a community server where the users have accounts, wiki editing can be limited
to the system's users.
In order to do this, install the *mod-authnz-external* module for Apache and the
*pwauth* binary. The module allows the password checking normally done inside
Apache to be done by an separate external program running outside of Apache.
Here's an example configuration:
```
AddExternalAuth pwauth /usr/sbin/pwauth
SetExternalAuthMethod pwauth pipe
<LocationMatch "^/(edit|save|add|append|upload|drop)/">
AuthType Basic
AuthName "Password Required"
AuthBasicProvider external
AuthExternal pwauth
Require valid-user
</LocationMatch>
```
## Different logins for different access rights
What if you have a site with various subdirectories and each subdirectory is for
a different group of friends? You can set this up using your webserver. One way
to do this is to require specific usernames (which must have a password in the
password file mentioned above.
This requires a valid login by the user "alex" or "berta":
```
<LocationMatch "^/(edit|save|add|append|upload|drop)/intetebi/">
Require user alex berta
</LocationMatch>
```
## Private wikis
Based on the above, you can prevent people from _reading_ the wiki. The location
must cover all the URLs in order to protect everything.
```
<Location />
AuthType Basic
AuthName "Password Required"
AuthUserFile /home/oddmu/.htpasswd
Require valid-user
</Location>
```
## Subdirectories as separate sites
The way Oddmu handles subdirectories is that all files and directories are
visible, except for "hidden" files and directories (whose name starts with a
period). Specifically, do not rely on Apache to hide locations in subdirectories
@@ -347,13 +292,42 @@ In this case, "/css/oddmu-2023.css" would be the name of your stylesheet. If
your document root is "/home/oddmu", then the filename of your stylesheet would
have to be "/home/oddmu/css/oddmu-2023.css" for this to work.
## Different logins for different access rights
What if you have a site with various subdirectories and each subdirectory is for
a different group of friends? You can set this up using your webserver. One way
to do this is to require specific usernames (which must have a password in the
password file mentioned above.
This requires a valid login by the user "alex" or "berta":
```
<LocationMatch "^/(edit|save|add|append|upload|drop)/intetebi/">
Require user alex berta
</LocationMatch>
```
## Private wikis
Based on the above, you can prevent people from _reading_ the wiki. The location
must cover all the URLs in order to protect everything.
```
<Location />
AuthType Basic
AuthName "Password Required"
AuthUserFile /home/oddmu/.htpasswd
Require valid-user
</Location>
```
## Virtual hosting
Virtual hosting in this context means that the program serves two different
sites for two different domains from the same machine. Oddmu doesn't support
that, but your webserver does. Therefore, start an Oddmu instance for every
domain name, each listening on a different port. Then set up your web server
such that every domain proxies for a different Oddmu instance.
such that ever domain acts as a reverse proxy to a different Oddmu instance.
# SEE ALSO

View File

@@ -5,7 +5,7 @@
.nh
.ad l
.\" Begin generated content:
.TH "ODDMU-EXPORT" "1" "2026-01-03"
.TH "ODDMU-EXPORT" "1" "2025-08-31"
.PP
.SH NAME
.PP
@@ -31,8 +31,7 @@ XML preamble is printed and appropriate escaping rules are used.\&
.PP
.SH FILES
.PP
By default, the export uses the feed template ("feed.\&html") in the current
directory.\&
By default, the export uses the \fB\fRfeed.\&html\fB\fR template in the current directory.\&
.PP
.SH EXAMPLES
.PP

View File

@@ -24,8 +24,7 @@ XML preamble is printed and appropriate escaping rules are used.
# FILES
By default, the export uses the feed template ("feed.html") in the current
directory.
By default, the export uses the **feed.html** template in the current directory.
# EXAMPLES

View File

@@ -5,7 +5,7 @@
.nh
.ad l
.\" Begin generated content:
.TH "ODDMU-FILTER" "7" "2026-01-03"
.TH "ODDMU-FILTER" "7" "2024-09-30"
.PP
.SH NAME
.PP
@@ -13,13 +13,13 @@ oddmu-filter - keeping subdirectories separate
.PP
.SH DESCRIPTION
.PP
There are actions such as producing the sitemap, searching and archiving that
act on multiple pages, not just a single page.\& These actions walk the directory
tree, including all subdirectories.\& In some cases, this is not desirable.\&
There are actions such as searching and archiving that act on multiple pages,
not just a single page.\& These actions walk the directory tree, including all
subdirectories.\& In some cases, this is not desirable.\&
.PP
Sometimes, subdirectories are separate sites, like the sites of other projects
or different people.\& Depending on how you think about it, you might not want to
include those "sites" in searches, sitemaps or archives of the whole site.\&
include those "sites" in searches or archives of the whole site.\&
.PP
Since directory tree actions always start in the directory the visitor is
currently looking at, directory tree actions starting in a "separate site"

View File

@@ -5,7 +5,7 @@
.nh
.ad l
.\" Begin generated content:
.TH "ODDMU-HTML" "1" "2026-01-03"
.TH "ODDMU-HTML" "1" "2025-04-05"
.PP
.SH NAME
.PP
@@ -13,7 +13,7 @@ oddmu-html - render Oddmu page HTML
.PP
.SH SYNOPSIS
.PP
\fBoddmu html\fR [\fB-template\fR \fItemplate-name\fR] \fIpage-name\fR
\fBoddmu html\fR [\fB\fR-template\fB\fR \fItemplate-name\fR] \fIpage-name\fR
.PP
.SH DESCRIPTION
.PP
@@ -23,7 +23,7 @@ name if you want to read Markdown from \fBstdin\fR.\&
.PP
.SH OPTIONS
.PP
\fB-template\fR \fItemplate-name\fR
\fB\fR-template\fB\fR \fItemplate-name\fR
.RS 4
Use the given template to render the page.\& Without this, the HTML lacks
html and body tags.\& The only two options that make sense are "view.\&html"

View File

@@ -6,7 +6,7 @@ oddmu-html - render Oddmu page HTML
# SYNOPSIS
*oddmu html* [*-template* _template-name_] _page-name_
*oddmu html* [**-template** _template-name_] _page-name_
# DESCRIPTION
@@ -16,7 +16,7 @@ name if you want to read Markdown from *stdin*.
# OPTIONS
*-template* _template-name_
**-template** _template-name_
Use the given template to render the page. Without this, the HTML lacks
html and body tags. The only two options that make sense are "view.html"
and "static.html".

View File

@@ -5,7 +5,7 @@
.nh
.ad l
.\" Begin generated content:
.TH "ODDMU-NGINX" "5" "2026-01-03"
.TH "ODDMU-NGINX" "5" "2025-07-16"
.PP
.SH NAME
.PP
@@ -27,7 +27,7 @@ section.\& Add a new \fIlocation\fR section after the existing \fIlocation\fR se
.PP
.nf
.RS 4
location ~ ^/(view|preview|diff|edit|save|add|append|upload|drop|search|sitemap|archive)/ {
location ~ ^/(view|preview|diff|edit|save|add|append|upload|drop|search|archive)/ {
proxy_pass http://localhost:8080;
}
.fi
@@ -97,7 +97,7 @@ server configuration.\& On a Debian system, that'\&d be in
.PP
.nf
.RS 4
location ~ ^/(view|preview|diff|edit|save|add|append|upload|drop|search|sitemap|archive)/ {
location ~ ^/(view|preview|diff|edit|save|add|append|upload|drop|search|archive)/ {
proxy_pass http://unix:/run/oddmu/oddmu\&.sock:;
}
.fi

View File

@@ -1,11 +1,11 @@
.\" Generated by scdoc 1.11.3
.\" Generated by scdoc 1.11.4
.\" Complete documentation for this program is not available as a GNU info page
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.nh
.ad l
.\" Begin generated content:
.TH "ODDMU-RELEASES" "7" "2026-02-06"
.TH "ODDMU-RELEASES" "7" "2026-01-01"
.PP
.SH NAME
.PP
@@ -15,10 +15,9 @@ oddmu-releases - what'\&s new?\&
.PP
This page lists user-visible features and template changes to consider.\&
.PP
.SS 1.20 (2026)
.SS 1.20 (unreleased)
.PP
Add -shrink and -glob options to the \fIstatic\fR subcommand.\& See \fIoddmu-static\fR(1)
for more.\&
Add -shrink and -glob options to the \fIstatic\fR subcommand.\&
.PP
Some tools were used to check the code (goimports, golint, gocritic).\&
Unfortunately, the resulting changes necessitates a change in the templates
@@ -41,8 +40,8 @@ faster than any of the feeds for hashtag pages, presumably, an extra features
was added: on the first and on the last page of the feed, a link to the next or
the previous year is added, if such a page exists.\& This works if at beginning of
every year, you move all the entries on to a dedicated year page.\& You need to
add the necessary links to the "feed.\&html" template.\& See \fIoddmu-templates\fR(5)
for more.\&
add the necessary links to the feed template ("feed.\&html").\& See
\fIoddmu-templates\fR(5) for more.\&
.PP
Example:
.PP
@@ -63,11 +62,6 @@ Example:
.fi
.RE
.PP
Add \fIsitemap\fR subcommand and handler.\& See \fIoddmu-sitemap\fR(1) for more.\& If you
want to make it available for search engines and the like, you most likely have
to add it to your proxy configuration.\& See \fIoddmu-apache\fR(5) or \fIoddmu-nginx\fR(5)
for more.\&
.PP
.SS 1.19 (2025)
.PP
Add \fIfeed\fR subcommand.\& This produces a "complete" feed.\&
@@ -77,8 +71,8 @@ Add feed pagination for the \fIfeed\fR action.\& This produces a "paginated" fee
See RFC 5005 for more information.\&
.PP
If you like the idea of feed pagination (not a given since that also helps bots
scrape your site!\&) you need to add the necessary links to the "feed.\&html"
template.\& See \fIoddmu-templates\fR(5) for more.\&
scrape your site!\&) you need to add the necessary links to the feed template
("feed.\&html").\& See \fIoddmu-templates\fR(5) for more.\&
.PP
Example, adding the feed history namespace:
.PP
@@ -110,15 +104,16 @@ In an effort to remove features that can be handled by the web server, the
for a better solution.\&
.PP
You probably need to remove a sentence linking to the list action from the
"upload.\&html" template.\&
upload template ("upload.\&html").\&
.PP
.SS 1.17 (2025)
.PP
You need to update the "upload.\&html" template.\& Many things have changed!\& See
\fIoddmu-templates\fR(5) for more.\&
You need to update the upload template ("upload.\&html").\& Many things have
changed!\& See \fIoddmu-templates\fR(5) for more.\&
.PP
You probably want to ensure that the upload link on the "view.\&html" template and
others, if you added it, has a \fIfilename\fR and \fIpagename\fR parameters.\&
You probably want to ensure that the upload link on the view template
("view.\&html") and others, if you added it, has a \fIfilename\fR and \fIpagename\fR
parameters.\&
.PP
Example:
.PP
@@ -128,8 +123,8 @@ Example:
.fi
.RE
.PP
You need to change {{.\&Name}} to {{.\&Path}} when it is used in URLs, in the
"list.\&html" template.\& If you don'\&t do this, file deleting and rename may not
You need to change {{.\&Name}} to {{.\&Path}} when it is used in URLs, in the list
template ("list.\&html").\& If you don'\&t do this, file deleting and rename may not
work on files containing a comma, a semicolon, a questionmark or a hash
character.\& This fix was necessary because URLs for files containing a
questionmark or a hash character would end the path at this character and treat
@@ -184,7 +179,7 @@ together with appropriate permission checks.\&
See \fIoddmu-apache\fR(5) or \fIoddmu-nginx\fR(5) for example.\&
.PP
In addition to that, you might want a link to the \fIlist\fR action from one of the
existing templates.\& For example, from the "upload.\&html" template:
existing templates.\& For example, from upload.\&html:
.PP
.nf
.RS 4
@@ -221,9 +216,10 @@ These are the quotation marks currently supported: '\&foo'\& "foo" foo
“foo” „foo“ ”foo” «foo» »foo« foo foo 「foo」 「foo」 『foo』 any such
quoted text is searched as-is, including whitespace.\&
.PP
Add loading="lazy" for images in the search template.\& If you want to take
advantage of this, you'\&ll need to adapt your "search.\&html" template accordingly.\&
Use like this, for example:
Add loading="lazy" for images in search.\&html
.PP
If you want to take advantage of this, you'\&ll need to adapt your "search.\&html"
template accordingly.\& Use like this, for example:
.PP
.nf
.RS 4
@@ -283,10 +279,10 @@ If you want to take advantage of this, you'\&ll need to adapt your templates
accordingly.\& The "preview.\&html" template is a mix of "view.\&html" and
"edit.\&html".\&
.PP
There is an optional change to make to copies of the "upload.\&html" template if
you upload multiple images at a time.\& Instead of showing just the link to the
last upload, you can now show the link (and the images or links, if you want to)
to all the files uploaded.\& Use like this, for example:
There is an optional change to make to copies of \fIupload.\&html\fR if you upload
multiple images at a time.\& Instead of showing just the link to the last upload,
you can now show the link (and the images or links, if you want to) to all the
files uploaded.\& Use like this, for example:
.PP
.nf
.RS 4
@@ -296,9 +292,9 @@ Links:<tt>{{range \&.Actual}}<br>![]({{\&.}}){{end}}</tt>
.PP
.SS 1.9 (2024)
.PP
There is a change to make to copies of the "upload.\&html" template if
subdirectories are being used.\& The \fILast\fR property no longer contains the
directory.\& It has to be added to the template as follows:
There is a change to make to copies of \fIupload.\&html\fR if subdirectories are being
used.\& The \fILast\fR property no longer contains the directory.\& It has to be added
to the template as follows:
.PP
.nf
.RS 4
@@ -326,7 +322,7 @@ The upload template can use the \fIToday\fR property.\&
The upload template comes with JavaScript that allows users to paste images or
drag and drop files.\&
.PP
The upload template changed the id for the filename field from "text" to "name".\&
The upload template changed the id for the filename field from `text` to `name`.\&
.PP
The source repository now comes with example templates.\&
.PP
@@ -336,7 +332,7 @@ No user-visible changes.\& Documentation and code comments got better.\&
.PP
.SS 1.7 (2024)
.PP
Allow upload of multiple files.\& This requires an update to the "upload.\&html"
Allow upload of multiple files.\& This requires an update to the \fIupload.\&html\fR
template: Add the \fImultiple\fR attribute to the file input element and change the
label from "file" to "files".\&
.PP

View File

@@ -8,10 +8,9 @@ oddmu-releases - what's new?
This page lists user-visible features and template changes to consider.
## 1.20 (2026)
## 1.20 (unreleased)
Add -shrink and -glob options to the _static_ subcommand. See _oddmu-static_(1)
for more.
Add -shrink and -glob options to the _static_ subcommand.
Some tools were used to check the code (goimports, golint, gocritic).
Unfortunately, the resulting changes necessitates a change in the templates
@@ -32,8 +31,8 @@ faster than any of the feeds for hashtag pages, presumably, an extra features
was added: on the first and on the last page of the feed, a link to the next or
the previous year is added, if such a page exists. This works if at beginning of
every year, you move all the entries on to a dedicated year page. You need to
add the necessary links to the "feed.html" template. See _oddmu-templates_(5)
for more.
add the necessary links to the feed template ("feed.html"). See
_oddmu-templates_(5) for more.
Example:
@@ -52,11 +51,6 @@ Example:
```
Add _sitemap_ subcommand and handler. See _oddmu-sitemap_(1) for more. If you
want to make it available for search engines and the like, you most likely have
to add it to your proxy configuration. See _oddmu-apache_(5) or _oddmu-nginx_(5)
for more.
## 1.19 (2025)
Add _feed_ subcommand. This produces a "complete" feed.
@@ -66,8 +60,8 @@ Add feed pagination for the _feed_ action. This produces a "paginated" feed.
See RFC 5005 for more information.
If you like the idea of feed pagination (not a given since that also helps bots
scrape your site!) you need to add the necessary links to the "feed.html"
template. See _oddmu-templates_(5) for more.
scrape your site!) you need to add the necessary links to the feed template
("feed.html"). See _oddmu-templates_(5) for more.
Example, adding the feed history namespace:
@@ -97,15 +91,16 @@ _list_, _delete_ and _rename_ actions were removed again. See _oddmu-webdav_(5)
for a better solution.
You probably need to remove a sentence linking to the list action from the
"upload.html" template.
upload template ("upload.html").
## 1.17 (2025)
You need to update the "upload.html" template. Many things have changed! See
_oddmu-templates_(5) for more.
You need to update the upload template ("upload.html"). Many things have
changed! See _oddmu-templates_(5) for more.
You probably want to ensure that the upload link on the "view.html" template and
others, if you added it, has a _filename_ and _pagename_ parameters.
You probably want to ensure that the upload link on the view template
("view.html") and others, if you added it, has a _filename_ and _pagename_
parameters.
Example:
@@ -113,8 +108,8 @@ Example:
<a href="/upload/{{.Dir}}?filename={{.Base}}-1.jpg&pagename={{.Base}}">Upload</a>
```
You need to change {{.Name}} to {{.Path}} when it is used in URLs, in the
"list.html" template. If you don't do this, file deleting and rename may not
You need to change {{.Name}} to {{.Path}} when it is used in URLs, in the list
template ("list.html"). If you don't do this, file deleting and rename may not
work on files containing a comma, a semicolon, a questionmark or a hash
character. This fix was necessary because URLs for files containing a
questionmark or a hash character would end the path at this character and treat
@@ -169,7 +164,7 @@ together with appropriate permission checks.
See _oddmu-apache_(5) or _oddmu-nginx_(5) for example.
In addition to that, you might want a link to the _list_ action from one of the
existing templates. For example, from the "upload.html" template:
existing templates. For example, from upload.html:
```
<p>You can rename and delete files <a href="/list/{{.Dir}}">from the file list</a>.
@@ -202,9 +197,10 @@ These are the quotation marks currently supported: 'foo' "foo" foo foo
“foo” „foo“ ”foo” «foo» »foo« foo foo 「foo」 「foo」 『foo』 any such
quoted text is searched as-is, including whitespace.
Add loading="lazy" for images in the search template. If you want to take
advantage of this, you'll need to adapt your "search.html" template accordingly.
Use like this, for example:
Add loading="lazy" for images in search.html
If you want to take advantage of this, you'll need to adapt your "search.html"
template accordingly. Use like this, for example:
```
{{range .Items}}
@@ -256,10 +252,10 @@ If you want to take advantage of this, you'll need to adapt your templates
accordingly. The "preview.html" template is a mix of "view.html" and
"edit.html".
There is an optional change to make to copies of the "upload.html" template if
you upload multiple images at a time. Instead of showing just the link to the
last upload, you can now show the link (and the images or links, if you want to)
to all the files uploaded. Use like this, for example:
There is an optional change to make to copies of _upload.html_ if you upload
multiple images at a time. Instead of showing just the link to the last upload,
you can now show the link (and the images or links, if you want to) to all the
files uploaded. Use like this, for example:
```
Links:<tt>{{range .Actual}}<br>![]({{.}}){{end}}</tt>
@@ -267,9 +263,9 @@ Links:<tt>{{range .Actual}}<br>![]({{.}}){{end}}</tt>
## 1.9 (2024)
There is a change to make to copies of the "upload.html" template if
subdirectories are being used. The _Last_ property no longer contains the
directory. It has to be added to the template as follows:
There is a change to make to copies of _upload.html_ if subdirectories are being
used. The _Last_ property no longer contains the directory. It has to be added
to the template as follows:
```
{{if ne .Last ""}}
@@ -293,7 +289,7 @@ The upload template can use the _Today_ property.
The upload template comes with JavaScript that allows users to paste images or
drag and drop files.
The upload template changed the id for the filename field from "text" to "name".
The upload template changed the id for the filename field from `text` to `name`.
The source repository now comes with example templates.
@@ -303,7 +299,7 @@ No user-visible changes. Documentation and code comments got better.
## 1.7 (2024)
Allow upload of multiple files. This requires an update to the "upload.html"
Allow upload of multiple files. This requires an update to the _upload.html_
template: Add the _multiple_ attribute to the file input element and change the
label from "file" to "files".

View File

@@ -1,49 +0,0 @@
.\" Generated by scdoc 1.11.3
.\" Complete documentation for this program is not available as a GNU info page
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.nh
.ad l
.\" Begin generated content:
.TH "ODDMU-SITEMAP" "1" "2026-01-03"
.PP
.SH NAME
.PP
oddmu-sitemap - print static sitemap.\&xml
.PP
.SH SYNOPSIS
.PP
\fBoddmu sitemap\fR [\fB-base\fR \fIURL\fR] [\fB-filter\fR \fIregexp\fR]
.PP
.SH DESCRIPTION
.PP
The "sitemap" subcommand prints the list of all pages in Sitemap format.\& Oddmu
already serves the sitemap at the URL "/sitemap.\&xml" but if you'\&d prefer to
provide a static file, use this command and redirect the output to a file called
"sitemap.\&xml" in your document root at regular intervals.\&
.PP
If you do this, don'\&t proxy the "/sitemap" URL in the web server configuration.\&
.PP
Your "robots.\&txt" file, if you have one, should point at the sitemap you
provide.\&
.PP
.SH OPTIONS
.PP
\fB-base\fR \fIURL\fR
.RS 4
The base URL is something like "https://example.\&org/view/".\&
.RE
\fB-filter\fR \fIregexp\fR
.RS 4
A regular expression matching the pages to exclude from the sitemap.\&
This emulates the effect of the ODDMU_FILTER environment variable.\&
.PP
.RE
.SH SEE ALSO
.PP
\fIoddmu\fR(1), \fIoddmu-filter\fR(7), \fIoddmu-apache\fR(1), \fIoddmu-nginx\fR(1),
https://www.\&sitemaps.\&org/
.PP
.SH AUTHORS
.PP
Maintained by Alex Schroeder <alex@gnu.\&org>.\&

View File

@@ -6,7 +6,7 @@ oddmu-sitemap - print static sitemap.xml
# SYNOPSIS
*oddmu sitemap* [*-base* _URL_] [*-filter* _regexp_]
*oddmu sitemap* [-base URL]
# DESCRIPTION

View File

@@ -1,11 +1,11 @@
.\" Generated by scdoc 1.11.3
.\" Generated by scdoc 1.11.4
.\" Complete documentation for this program is not available as a GNU info page
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.nh
.ad l
.\" Begin generated content:
.TH "ODDMU-STATIC" "1" "2026-02-06"
.TH "ODDMU-STATIC" "1" "2025-12-05"
.PP
.SH NAME
.PP
@@ -13,7 +13,7 @@ oddmu-static - create a static copy of the site
.PP
.SH SYNOPSIS
.PP
\fBoddmu static\fR [\fB-jobs\fR \fIn\fR] [\fB-glob\fR \fIpattern\fR] [\fB-shrink\fR] \fIdir-name\fR
\fBoddmu static\fR [\fB\fR-jobs\fB\fR \fIn\fR] [\fB\fR-glob\fB\fR \fIpattern\fR] [\fB\fR-shrink\fB\fR] \fIdir-name\fR
.PP
.SH DESCRIPTION
.PP
@@ -32,7 +32,7 @@ no feed items are found, no feed is written.\& The feed is limited to the ten mo
recent items.\&
.PP
Hidden files and directories (starting with a ".\&") and backup files (ending with
a "~") are skipped.\&
a "\(ti") are skipped.\&
.PP
All other files are \fIhard linked\fR.\& This is done to save space: on a typical blog
the images take a lot more space than the text.\& On my blog in 2023 I had 2.\&62
@@ -53,18 +53,18 @@ original, too.\&
.PP
.SH OPTIONS
.PP
\fB-jobs\fR \fIn\fR
\fB\fR-jobs\fB\fR \fIn\fR
.RS 4
By default, two jobs are used to process the files.\& If your machine has
more cores, you can increase the number of jobs.\&
.PP
.RE
\fB-glob\fR \fIpattern\fR
\fB\fR-glob\fB\fR \fIpattern\fR
.RS 4
By default, all files are used for the static export.\& You can limit the
files used by providing a shell file name pattern.\& A "*" matches any
number of characters; a "?\&" matches exactly one character; "[a-z]"
matches a character listed, including ranges; "[^a-z]" matches a
matches a character listed, including ranges; "[\(haa-z]" matches a
character not listed, including ranges; "\e" a backslash escapes the
following character.\& You must use quotes around the pattern if you are
using a shell as the shell would otherwise expand the pattern, resulting
@@ -72,12 +72,12 @@ in the error "Exactly one target directory is required".\&
.PP
.PP
.RE
\fB-shrink\fR
\fB\fR-shrink\fB\fR
.RS 4
By default, images are linked or copied.\& With this option, JPEG, PNG and
WebP files are scaled down if more than 800 pixels wide and the quality
is set to 30% for JPEG and WebP files.\& This is \fIbad quality\fR but the
result is that these image files are very small.\&
is set to 10% for JPEG and WebP files.\& This is \fIvery bad quality\fR but
the result is that these image files are very small.\&
.PP
.RE
.SH EXAMPLES

View File

@@ -6,7 +6,7 @@ oddmu-static - create a static copy of the site
# SYNOPSIS
*oddmu static* [*-jobs* _n_] [*-glob* _pattern_] [*-shrink*] _dir-name_
*oddmu static* [**-jobs** _n_] [**-glob** _pattern_] [**-shrink**] _dir-name_
# DESCRIPTION
@@ -46,11 +46,11 @@ original, too.
# OPTIONS
*-jobs* _n_
**-jobs** _n_
By default, two jobs are used to process the files. If your machine has
more cores, you can increase the number of jobs.
*-glob* _pattern_
**-glob** _pattern_
By default, all files are used for the static export. You can limit the
files used by providing a shell file name pattern. A "\*" matches any
number of characters; a "?" matches exactly one character; "[a-z]"
@@ -61,11 +61,11 @@ original, too.
in the error "Exactly one target directory is required".
*-shrink*
**-shrink**
By default, images are linked or copied. With this option, JPEG, PNG and
WebP files are scaled down if more than 800 pixels wide and the quality
is set to 30% for JPEG and WebP files. This is _bad quality_ but the
result is that these image files are very small.
is set to 10% for JPEG and WebP files. This is _very bad quality_ but
the result is that these image files are very small.
# EXAMPLES

View File

@@ -1,11 +1,11 @@
.\" Generated by scdoc 1.11.3
.\" Generated by scdoc 1.11.4
.\" Complete documentation for this program is not available as a GNU info page
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.nh
.ad l
.\" Begin generated content:
.TH "ODDMU-TEMPLATES" "5" "2026-01-03" "File Formats Manual"
.TH "ODDMU-TEMPLATES" "5" "2026-01-01" "File Formats Manual"
.PP
.SH NAME
.PP
@@ -31,12 +31,12 @@ placeholders.\&
.IP \(bu 4
\fIfeed.\&html\fR uses a \fIfeed\fR
.IP \(bu 4
\fIlist.\&html\fR uses a \fIlist\fR
.IP \(bu 4
\fIpreview.\&html\fR uses a \fIpage\fR
.IP \(bu 4
\fIsearch.\&html\fR uses a \fIsearch\fR
.IP \(bu 4
\fIsitemap.\&html\fR uses a \fIsitemap\fR
.IP \(bu 4
\fIstatic.\&html\fR uses a \fIpage\fR
.IP \(bu 4
\fIupload.\&html\fR uses an \fIupload\fR
@@ -172,6 +172,32 @@ explanation.\& The next year is one lower than the year currently shown (if on a
year page) or the current year (if looking at the index).\& If it isn'\&t set, it'\&s
value is 0.\&
.PP
.SS List
.PP
The list contains a directory name and an array of files.\&
.PP
\fI{{.\&Dir}}\fR is the directory name that is being listed, percent-encoded.\&
.PP
\fI{{.\&Files}}\fR is the array of files.\& To refer to them, you need to use a \fI{{range
Files}}\fR\fI{{end}}\fR construct.\&
.PP
Each file has the following attributes:
.PP
\fI{{.\&Name}}\fR is the filename.\& The ".\&md" suffix for Markdown files is part of the
name (unlike page names).\&
.PP
\fI{{.\&Path}}\fR is the page name, percent-encoded.\&
.PP
\fI{{.\&Title}}\fR is the page title, if the file in question is a Markdown file.\&
.PP
\fI{{.\&IsDir}}\fR is a boolean used to indicate that this file is a directory.\&
.PP
\fI{{.\&IsUp}}\fR is a boolean used to indicate the entry for the parent directory
(the first file in the array, unless the directory being listed is the top
directory).\& The filename of this file is ".\&.\&".\&
.PP
\fI{{.\&Date}}\fR is the last modification date of the file.\&
.PP
.SS Search
.PP
\fI{{.\&Query}}\fR is the query string.\&
@@ -210,16 +236,6 @@ are only listed if a search term matches.\&
\fI{{.\&Html}}\fR the image alt-text with a bold tag used to highlight the first
search term that matched.\&
.PP
.SS Sitemap
.PP
The sitemap contains a list of URLs, each with its location:
.PP
\fI{{.\&URL}}\fR is the list of URLs.\&
.PP
Each URL has the following attributes:
.PP
\fI{{.\&Loc}}\fR with the actual page URL.\&
.PP
.SS Upload
.PP
\fI{{.\&Dir}}\fR is the directory where the uploaded file ends up, based on the URL

View File

@@ -1,425 +0,0 @@
.\" Generated by scdoc 1.11.3
.\" Complete documentation for this program is not available as a GNU info page
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.nh
.ad l
.\" Begin generated content:
.TH "ODDMU" "1" "2026-01-03"
.PP
.SH NAME
.PP
oddmu - a wiki server
.PP
Oddmu is sometimes written Oddμ because μ is the letter mu.\&
.PP
.SH SYNOPSIS
.PP
\fBoddmu\fR
.PP
\fBoddmu\fR \fIsubcommand\fR [\fIarguments\fR.\&.\&.\&]
.PP
.SH DESCRIPTION
.PP
Oddmu can be used as a static site generator, turning Markdown files into HTML
files, or it can be used as a public or a private wiki server.\& If it runs as a
public wiki server, a regular webserver should be used as reverse proxy.\&
.PP
Run Oddmu without any arguments to serve the current working directory as a wiki
on port 8080.\& Point your browser to http://localhost:8080/ to use it.\& This
redirects you to http://localhost:8080/view/index the first page you'\&ll
create, most likely.\&
.PP
See \fIoddmu\fR(5) for details about the page formatting.\&
.PP
If you request a page that doesn'\&t exist, Oddmu tries to find a matching
Markdown file by appending the extension ".\&md" to the page name.\& In the example
above, the page name requested is "index" and the file name Oddmu tries to read
is "index.\&md".\& If no such file exists, Oddmu offers you to create the page.\&
.PP
If your files don'\&t provide their own title ("# title"), the file name (without
".\&md") is used for the page title.\&
.PP
Every file can be viewed as feed by using the extension ".\&rss".\& The
feed items are based on links in bullet lists using the asterix
("*").\&
.PP
Subdirectories are created as necessary.\&
.PP
The wiki knows the following actions for a given page name and (optional)
directory:
.PP
.PD 0
.IP \(bu 4
\fI/\fR redirects to /view/index
.IP \(bu 4
\fI/view/dir/\fR redirects to /view/dir/index
.IP \(bu 4
\fI/view/dir/name\fR shows a page
.IP \(bu 4
\fI/view/dir/name.\&md\fR shows the source text of a page
.IP \(bu 4
\fI/view/dir/name.\&rss\fR shows the RSS feed for the pages linked
.IP \(bu 4
\fI/diff/dir/name\fR shows the last change to a page
.IP \(bu 4
\fI/edit/dir/name\fR shows a form to edit a page
.IP \(bu 4
\fI/preview/dir/name\fR shows a preview of a page edit and the form to edit it
.IP \(bu 4
\fI/save/dir/name\fR saves an edit
.IP \(bu 4
\fI/add/dir/name\fR shows a form to add to a page
.IP \(bu 4
\fI/append/dir/name\fR appends an addition to a page
.IP \(bu 4
\fI/upload/dir/name\fR shows a form to upload a file
.IP \(bu 4
\fI/drop/dir/name\fR saves an upload
.IP \(bu 4
\fI/search/dir/?\&q=term\fR to search for a term
.IP \(bu 4
\fI/sitemap.\&xml\fR to list the links to all the pages
.IP \(bu 4
\fI/archive/dir/name.\&zip\fR to download a zip file of a directory
.PD
.PP
When calling the \fIsave\fR and \fIappend\fR action, the page name is taken from the URL
path and the page content is taken from the \fIbody\fR form parameter.\& To
illustrate, here'\&s how to edit the "welcome" page using \fIcurl\fR:
.PP
.nf
.RS 4
curl --form body="Did you bring a towel?"
http://localhost:8080/save/welcome
.fi
.RE
.PP
When calling the \fIdrop\fR action, the query parameters used are \fIname\fR for the
target filename and \fIfile\fR for the file to upload.\& If the query parameter
\fImaxwidth\fR is set, an attempt is made to decode and resize the image.\& JPG, PNG,
WEBP and HEIC files can be decoded.\& Only JPG and PNG files can be encoded,
however.\& If the target name ends in \fI.\&jpg\fR, the \fIquality\fR query parameter is
also taken into account.\& To upload some thumbnails:
.PP
.nf
.RS 4
for f in *\&.jpg; do
curl --form name="$f" --form file=@"$f" --form maxwidth=100
http://localhost:8080/drop/
done
.fi
.RE
.PP
When calling the \fIsearch\fR action, the search terms are taken from the query
parameter \fIq\fR.\&
.PP
.nf
.RS 4
curl \&'http://localhost:8080/search/?q=towel\&'
.fi
.RE
.PP
The page name to act upon is optionally taken from the query parameter \fIid\fR.\& In
this case, the directory must also be part of the query parameter and not of the
URL path.\&
.PP
.nf
.RS 4
curl \&'http://localhost:8080/view/?id=man/oddmu\&.1\&.txt\&'
.fi
.RE
.PP
The base name for the \fIarchive\fR action is used by the browser to save the
downloaded file.\& For Oddmu, only the directory is important.\& The following zips
the \fIman\fR directory and saves it as \fIman.\&zip\fR.\&
.PP
.nf
.RS 4
curl --remote-name \&'http://localhost:8080/archive/man/man\&.zip
.fi
.RE
.PP
.SH CONFIGURATION
.PP
The template files are the HTML files in the working directory.\& Please change
these templates!\&
.PP
The first change you should make is to replace the name and email address in the
footer of \fIview.\&html\fR.\& Look for "Your Name" and "example.\&org".\&
.PP
The second change you should make is to replace the name, email address and
domain name in "feed.\&html".\& Look for "Your Name" and "example.\&org".\&
.PP
See \fIoddmu-templates\fR(5) for more.\&
.PP
.SH ENVIRONMENT
.PP
You can change the port served by setting the ODDMU_PORT environment variable.\&
.PP
You can change the address served by setting the ODDMU_ADDRESS environment
variable to either an IPv4 address or an IPv6 address.\& If ODDMU_ADDRESS is
unset, then the program listens on all available unicast addresses, both IPv4
and IPv6.\& Here are a few example addresses:
.PP
.nf
.RS 4
ODDMU_ADDRESS=127\&.0\&.0\&.1 # The loopback IPv4 address\&.
ODDMU_ADDRESS=2001:db8::3:1 # An IPv6 address\&.
.fi
.RE
.PP
See the Socket Activation section for an alternative method of listening which
supports Unix-domain sockets.\&
.PP
In order to limit language-detection to the languages you actually use, set the
environment variable ODDMU_LANGUAGES to a comma-separated list of ISO 639-1
codes, e.\&g.\& "en" or "en,de,fr,pt".\&
.PP
You can enable webfinger to link fediverse accounts to their correct profile
pages by setting ODDMU_WEBFINGER to "1".\& See \fIoddmu\fR(5).\&
.PP
If you use secret subdirectories, you cannot rely on the web server to hide
those pages because some actions such as searching and archiving include
subdirectories.\& They act upon a whole tree of pages, not just a single page.\& The
ODDMU_FILTER can be used to exclude subdirectories from such tree actions.\& See
\fIoddmu-filter\fR(7) and \fIoddmu-apache\fR(5).\&
.PP
.SH Socket Activation
.PP
Instead of specifying ODDMU_ADDRESS or ODDMU_PORT, you can start the service
through socket activation.\& The advantage of this method is that you can use a
Unix-domain socket instead of a TCP socket, and the permissions and ownership of
the socket are set before the program starts.\& See \fIoddmu.\&service\fR(5),
\fIoddmu-apache\fR(5) and \fIoddmu-nginx\fR(5) for an example of how to use socket
activation with a Unix-domain socket under systemd and Apache.\&
.PP
.SH SECURITY
.PP
If the machine you are running Oddmu on is accessible from the Internet, you
must secure your installation.\& The best way to do this is use a regular web
server as a reverse proxy.\& See \fIoddmu-apache\fR(5) and \fIoddmu-nginx\fR(5) for
example configurations.\&
.PP
Oddmu assumes that all the users that can edit pages or upload files are trusted
users and therefore their content is trusted.\& Oddmu does not perform HTML
sanitization!\&
.PP
For an extra dose of security, consider using a Unix-domain socket.\&
.PP
.SH OPTIONS
.PP
Oddmu can be run on the command-line using various subcommands.\&
.PP
.PD 0
.IP \(bu 4
to generate the HTML for a single page, see \fIoddmu-html\fR(1)
.IP \(bu 4
to generate the HTML for the entire site, using Oddmu as a static site
generator, see \fIoddmu-static\fR(1)
.IP \(bu 4
to export the HTML for the entire site in one big feed, see \fIoddmu-export\fR(1)
.IP \(bu 4
to emulate a search of the files, see \fIoddmu-search\fR(1); to understand how the
search engine indexes pages and how it sorts and scores results, see
\fIoddmu-search\fR(7)
.IP \(bu 4
to search a regular expression and replace it across all files, see
\fIoddmu-replace\fR(1)
.IP \(bu 4
to learn what the most popular hashtags are, see \fIoddmu-hashtags\fR(1)
.IP \(bu 4
to print a table of contents (TOC) for a page, see \fIoddmu-toc\fR(1)
.IP \(bu 4
to list the outgoing links for a page, see \fIoddmu-links\fR(1)
.IP \(bu 4
to find missing pages (local links that go nowhere), see \fIoddmu-missing\fR(1)
.IP \(bu 4
to list all the pages with name and title, see \fIoddmu-list\fR(1)
.IP \(bu 4
to add links to changes, index and hashtag pages to pages you created locally,
see \fIoddmu-notify\fR(1)
.IP \(bu 4
to display build information, see \fIoddmu-version\fR(1)
.PD
.PP
.SH EXAMPLES
.PP
When saving a page, the page name is take from the URL and the page content is
taken from the "body" form parameter.\& To illustrate, here'\&s how to edit a page
using \fIcurl\fR(1):
.PP
.nf
.RS 4
curl --form body="Did you bring a towel?"
http://localhost:8080/save/welcome
.fi
.RE
.PP
To compute the space used by your setup, use regular tools:
.PP
.nf
.RS 4
du --exclude=\&'*/.*\&' --exclude \&'*~\&' --block-size=M
.fi
.RE
.PP
.SH DESIGN
.PP
This is a minimal wiki.\& There is no version history.\& It'\&s well suited as a
\fIsecondary\fR medium: collaboration and conversation happens elsewhere, in chat,
on social media.\& The wiki serves as the text repository that results from these
discussions.\&
.PP
The idea is that the webserver handles as many tasks as possible.\& It logs
requests, does rate limiting, handles encryption, gets the certificates, and so
on.\& The web server acts as a reverse proxy and the wiki ends up being a content
management system with almost no structure or endless malleability, depending
on your point of view.\& See \fIoddmu-apache\fR(5).\&
.PP
.SH NOTES
.PP
Page names are filenames with ".\&md" appended.\& If your filesystem cannot handle
it, it can'\&t be a page name.\& Filenames can contain slashes and Oddmu creates
subdirectories as necessary.\&
.PP
Files may not end with a tilde ('\&~'\&) these are backup files.\& When saving pages
and file uploads, the old file is renamed to the backup file unless the backup
file is less than an hour old, thus collapsing all edits made in an hour into a
single diff when comparing backup and current version.\& The backup also gets an
updated timestamp so that subsequent edits don'\&t immediately overwrite it.\&
.PP
The \fBindex\fR page is the default page.\& People visiting the "root" of the site are
redirected to "/view/index".\&
.PP
The \fBchanges\fR page is where links to new and changed files are added.\& As an
author, you can prevent this from happening by deselecting the checkbox "Add
link to the list of changes.\&" The changes page can be edited like every other
page, so it'\&s easy to undo mistakes.\&
.PP
Links on the changes page are grouped by date.\& When new links are added, the
current date of the machine Oddmu is running on is used.\& If a link already
exists on the changes page, it is moved up to the current date.\& If that leaves
an old date without any links, that date heading is removed.\&
.PP
If you want to link to the changes page, you need to do this yourself.\& Add a
link from the index, for example.\& The "view.\&html" template currently doesn'\&t do
it.\& See \fIoddmu-templates\fR(5) if you want to add the link to the template.\&
.PP
A page whose name starts with an ISO date (YYYY-MM-DD, e.\&g.\& "2023-10-28") is
called a \fBblog\fR page.\& When creating or editing blog pages, links to it are added
from other pages.\&
.PP
If the blog page name starts with the current year, a link is created from the
index page back to the blog page being created or edited.\& Again, you can prevent
this from happening by deselecting the checkbox "Add link to the list of
changes.\&" The index page can be edited like every other page, so it'\&s easy to
undo mistakes.\&
.PP
For every \fBhashtag\fR used, another link might be created.\& If a page named like
the hashtag exists, a backlink is added to it, linking to the new or edited blog
page.\&
.PP
If a link to the new or edited blog page already exists but it'\&s title is no
longer correct, it is updated.\&
.PP
New links added for blog pages are added at the top of the first unnumbered list
using the asterisk ('\&*'\&).\& If no such list exists, a new one is started at the
bottom of the page.\& This allows you to have a different unnumbered list further
up on the page, as long as it uses the minus for items ('\&-'\&).\&
.PP
Changes made locally do not create any links on the changes page, the index page
or on any hashtag pages.\& See \fIoddmu-notify\fR(1) for a way to add the necessary
links to the changes page and possibly to the index and hashtag pages.\&
.PP
A hashtag consists of a number sign ('\&#'\&) followed by Unicode letters, numbers
or the underscore ('\&_'\&).\& Thus, a hashtag ends with punctuation or whitespace.\&
.PP
The page names, titles and hashtags are loaded into memory when the server
starts.\& If you have a lot of pages, this takes a lot of memory.\&
.PP
Oddmu watches the working directory and any subdirectories for changes made
directly.\& Thus, in theory, it'\&s not necessary to restart it after making such
changes.\&
.PP
You cannot edit uploaded files.\& If you upload a file called "hello.\&txt" and
attempt to edit it by using "/edit/hello.\&txt" you create a page with the name
"hello.\&txt.\&md" instead.\&
.PP
In order to delete uploaded files via the web, create an empty file and upload
it.\& In order to delete a wiki page, save an empty page.\&
.PP
Note that some HTML file names are special: they act as templates.\& See
\fIoddmu-templates\fR(5) for their names and their use.\&
.PP
.SH SEE ALSO
.PP
.PD 0
.IP \(bu 4
\fIoddmu\fR(5), about the markup syntax and how feeds are generated based on link
lists
.IP \(bu 4
\fIoddmu-releases\fR(7), on what features are part of the latest release
.IP \(bu 4
\fIoddmu-filter\fR(7), on how to treat subdirectories as separate sites
.IP \(bu 4
\fIoddmu-search\fR(7), on how search works
.IP \(bu 4
\fIoddmu-templates\fR(5), on how to write the HTML templates
.PD
.PP
If you run Oddmu as a web server:
.PP
.PD 0
.IP \(bu 4
\fIoddmu-apache\fR(5), on how to set up Apache as a reverse proxy
.IP \(bu 4
\fIoddmu-nginx\fR(5), on how to set up freenginx as a reverse proxy
.IP \(bu 4
\fIoddmu-webdav\fR(5), on how to set up Apache as a Web-DAV server
.IP \(bu 4
\fIoddmu.\&service\fR(5), on how to run the service under systemd
.PD
.PP
If you run Oddmu as a static site generator or pages offline and sync them with
Oddmu running as a webserver:
.PP
.PD 0
.IP \(bu 4
\fIoddmu-hashtags\fR(1), on working with hashtags
.IP \(bu 4
\fIoddmu-html\fR(1), on how to render a page
.IP \(bu 4
\fIoddmu-feed\fR(1), on how to render a feed
.IP \(bu 4
\fIoddmu-list\fR(1), on how to list pages and titles
.IP \(bu 4
\fIoddmu-links\fR(1), on how to list the outgoing links for a page
.IP \(bu 4
\fIoddmu-missing\fR(1), on how to find broken local links
.IP \(bu 4
\fIoddmu-notify\fR(1), on updating index, changes and hashtag pages
.IP \(bu 4
\fIoddmu-replace\fR(1), on how to search and replace text
.IP \(bu 4
\fIoddmu-search\fR(1), on how to run a search
.IP \(bu 4
\fIoddmu-sitemap\fR(1), on generating a static sitemap.\&xml
.IP \(bu 4
\fIoddmu-static\fR(1), on generating a static site
.IP \(bu 4
\fIoddmu-toc\fR(1), on how to list the table of contents (toc) a page
.IP \(bu 4
\fIoddmu-version\fR(1), on how to get all the build information from the binary
.PD
.PP
If you want to stop using Oddmu:
.PP
.PD 0
.IP \(bu 4
\fIoddmu-export\fR(1), on how to export all the files as one big RSS file
.PD
.PP
.SH AUTHORS
.PP
Maintained by Alex Schroeder <alex@gnu.\&org>.\&

View File

@@ -1,7 +1,6 @@
package main
import (
"fmt"
"log"
"net/http"
"os"
@@ -22,12 +21,8 @@ func sitemapHandler(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/sitemap.xml" {
http.NotFound(w, r)
} else {
w.Write([]byte(`<?xml version="1.0" encoding="UTF-8"?>` + "\n"))
scheme := "http"
if r.TLS != nil {
scheme += "s"
}
base := fmt.Sprintf("%s://%s/view/", scheme, r.Host)
w.Write([]byte(`<?xml version="1.0" encoding="UTF-8"?>`))
base := r.URL.Scheme + "://" + r.URL.Host + "/view/"
filter := os.Getenv("ODDMU_FILTER")
renderTemplate(w, ".", "sitemap", sitemap(&index, base, filter))
}
@@ -45,7 +40,7 @@ func sitemap(idx *indexStore, base, filter string) Sitemap {
idx.RLock()
defer idx.RUnlock()
for name := range idx.titles {
if filter == "" || !re.MatchString(name) {
if !re.MatchString(name) {
url = append(url, &SitemapURL{Loc: base + name})
}
}

View File

@@ -24,9 +24,6 @@ import (
"github.com/google/subcommands"
)
var shrinkWidth = 800
var shrinkQuality = 30
type staticCmd struct {
jobs int
shrink bool
@@ -262,6 +259,9 @@ func staticFile(source, target string, info fs.FileInfo, shrink bool) error {
return err
}
var shrinkWidth = 800
var shrinkQuality = 10
// shrink Image shrinks images down and reduces the quality dramatically.
func shrinkImage(source, target string, info fs.FileInfo) error {
file, err := os.Open(source)

View File

@@ -208,7 +208,7 @@ func serve() {
mux.HandleFunc("/upload/", makeHandler(uploadHandler, false, http.MethodGet))
mux.HandleFunc("/drop/", makeHandler(dropHandler, false, http.MethodPost))
mux.HandleFunc("/search/", makeHandler(searchHandler, false, http.MethodGet, http.MethodPost))
mux.HandleFunc("/sitemap.xml", sitemapHandler)
mux.HandleFunc("/sitemap", sitemapHandler)
srv := &http.Server{
ReadTimeout: 2 * time.Minute,
WriteTimeout: 5 * time.Minute,