136 lines
5.5 KiB
Racket
136 lines
5.5 KiB
Racket
#lang scribble/manual
|
|
|
|
@(require (for-label racket/base
|
|
racket/contract
|
|
racket/path
|
|
racket-wiki
|
|
racket-wiki/translate))
|
|
|
|
@title{racket-wiki}
|
|
@author[@author+email["Hans Dijkema" "hans@dijkewijk.nl"]]
|
|
|
|
@defmodule[racket-wiki]
|
|
|
|
The @racketmodname[racket-wiki] module starts a small self-hosted Markdown wiki.
|
|
Racket provides the HTTP API, authentication, PostgreSQL-backed user and page
|
|
storage, versioning, full-text search, and the initial web setup. Markdown
|
|
rendering and the editing interface run in the browser.
|
|
|
|
@section{Starting the Wiki}
|
|
|
|
@defproc[(start
|
|
[#:data-dir data-dir path-string? "wiki-data"]
|
|
[#:port port exact-positive-integer? 8080]
|
|
[#:listen-ip listen-ip (or/c string? #f) "127.0.0.1"]
|
|
[#:secure-cookie? secure-cookie? boolean? #f]
|
|
[#:site-title site-title string? "Racket Wiki"]
|
|
[#:session-seconds session-seconds exact-positive-integer? (* 12 60 60)]
|
|
[#:language language string? "en"])
|
|
any] {
|
|
Starts the wiki using explicit server parameters. The data directory is made
|
|
absolute before the server starts.
|
|
|
|
Use @racket["*"] or @racket[#f] for @racket[listen-ip] to listen on all
|
|
interfaces. The default address only listens on the local machine.
|
|
|
|
This procedure is the convenient entry point when starting the wiki from
|
|
DrRacket or another interactive Racket session.
|
|
}
|
|
|
|
@defproc*[([(start-wiki) any]
|
|
[(start-wiki [config any/c]) any])] {
|
|
Starts the wiki using either the default configuration or the supplied wiki
|
|
configuration.
|
|
}
|
|
|
|
@section{Initial Setup}
|
|
|
|
When PostgreSQL has not been configured, the schema is unavailable, no enabled
|
|
administrator exists, or one of the required browser libraries is missing,
|
|
normal application requests are redirected to @tt{/setup}.
|
|
|
|
The setup page itself requires no JavaScript. On a fresh installation it asks for
|
|
PostgreSQL server, port, database, user, password and SSL mode. The database must
|
|
already exist. After testing the connection, setup creates the racket-wiki schema,
|
|
asks for the first administrator, and downloads the pinned EasyMDE, Font Awesome,
|
|
DOMPurify, highlight.js, and diff2html browser files. PostgreSQL connection
|
|
settings are stored in @tt{database.rktd} below the configured data directory.
|
|
After setup the browser is redirected to @tt{/login}; setup does not create an
|
|
authenticated browser session.
|
|
|
|
|
|
@section{Page Slugs}
|
|
|
|
For a normal new page, the backend derives the slug from the title when the page
|
|
is first saved. A later title change leaves the slug unchanged so existing links
|
|
remain stable.
|
|
|
|
When an editor or administrator follows a wiki-page link to a slug that does not
|
|
yet exist, the browser opens an empty create view for that requested slug. A
|
|
reader receives a normal not-found view. Unauthenticated browser requests are
|
|
redirected to @tt{/login} before the wiki application is served.
|
|
|
|
|
|
@section{Page contents}
|
|
|
|
The application sidebar gives the current page's headings priority over the
|
|
global page list. The contents list follows Markdown headings and is updated
|
|
while a page is edited.
|
|
|
|
@section{Editor appearance}
|
|
|
|
EasyMDE and the rendered wiki page use matching body and heading sizes. The
|
|
source editor keeps Markdown syntax visible, but heading text uses the same
|
|
scale as the rendered page. Toolbar icons are provided by a locally installed
|
|
Font Awesome copy.
|
|
|
|
|
|
@section{Page navigation and metadata}
|
|
|
|
The sidebar gives priority to a table of contents derived from the headings in
|
|
the current Markdown document. The page list is secondary. The editor updates
|
|
the table of contents while the document is being edited.
|
|
|
|
A breadcrumb is displayed above the document. The footer displays creation and
|
|
modification timestamps, the current version, and page tags. Tags are stored in
|
|
the page metadata and version metadata.
|
|
|
|
@section{Full-text search}
|
|
|
|
Current pages are indexed by PostgreSQL using a weighted @tt{tsvector}; title
|
|
terms have a higher weight than Markdown body terms. A GIN index accelerates
|
|
searches. The wiki uses PostgreSQL's @tt{simple} text-search configuration so
|
|
technical Dutch, English and identifier-like terms are not subjected to a
|
|
language-specific stemmer.
|
|
|
|
@section{Database schema migrations}
|
|
|
|
Racket Wiki records PostgreSQL schema migrations in @tt{wiki_schema}. The current page is stored in @tt{pages}; every saved historical revision is stored in @tt{page_versions}. Attachments, including their binary content, are stored in @tt{attachments}. Schema migrations run in order when the application starts.
|
|
|
|
@section{Todo items}
|
|
|
|
Wiki-wide todo items are written as @tt{todo(text)} in Markdown. Markers inside
|
|
fenced code blocks are ignored. Current todo markers are indexed in PostgreSQL
|
|
and collected in the Todo view. Ordinary Markdown task lists remain available
|
|
for page-local checklists.
|
|
|
|
@section{Translations}
|
|
|
|
@defmodule[racket-wiki/translate]
|
|
|
|
@defproc[(tr [config any/c] [key symbol?]) string?] {
|
|
Returns the effective UI translation for @racket[key]. Built-in English and
|
|
Dutch translations are available before the database is configured. Once the
|
|
database is available, assignments in the special
|
|
@tt{wiki-translations-<language>} page override the built-in strings.
|
|
}
|
|
|
|
The UI language is selected with @tt{--language} or @racket[#:language]. The
|
|
frontend obtains the same effective table from the server, so server and browser
|
|
labels use one translation source.
|
|
|
|
@section{Connectivity}
|
|
|
|
The browser calls @tt{/api/ping} every 15 seconds. Failed or timed-out requests
|
|
show an Offline indicator. A recovered connection briefly shows Online.
|