From ea7cd45eed40b3f3325e618334b53b607be82df2 Mon Sep 17 00:00:00 2001 From: Hans Dijkema Date: Sat, 15 Aug 2026 01:46:15 +0200 Subject: [PATCH] breadcrumps, todos, etc. --- Makefile | 2 +- README.md | 21 +++ info.rkt | 2 +- private/migrations.rkt | 32 ++++- private/storage.rkt | 110 +++++++++++++++ private/todo.rkt | 2 +- server.rkt | 46 ++++++ static/css/wiki.css | 102 ++++++++++++++ static/index.html | 24 ++++ static/js/wiki.js | 313 ++++++++++++++++++++++++++++++++++++++--- translate.rkt | 8 +- 11 files changed, 635 insertions(+), 27 deletions(-) diff --git a/Makefile b/Makefile index c1601f5..695b7eb 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ (target zip (deps clean) - (zip-package)) + (zip-package #:exclude '("wiki-data"))) (target clean (for-each (λ (f) (displayln f) (rm-f f)) (list-files "." #px"([.]bak|~)$" #:recursive #t)) diff --git a/README.md b/README.md index 81f9b02..a820a77 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # racket-wiki +Current development version: **0.2.19**. + A small self-hosted wiki with a Racket backend and an HTML5/CSS/JavaScript frontend. Version 0.2.9 uses PostgreSQL as the wiki's complete content store. Users, sessions, pages, immutable page versions, attachment metadata and attachment bytes live in PostgreSQL. PostgreSQL full-text search is built into the page table and exposed by the wiki search UI. @@ -344,3 +346,22 @@ Version 0.2.13 centers the wiki name in the sidebar and makes it a link to the f ## 0.2.15 The page table of contents now includes a `(context)` link. It opens a graph containing the current page and all pages that link directly to it or are linked directly from it. The current page is highlighted. Heading anchors also reserve space for the sticky top navigation so a selected heading remains visible. + + +## Recent pages and bookmarks + +The sidebar provides dynamic Recent and Bookmarks views. Recent shows current pages ordered by their last edit time. Bookmarks are stored per user in PostgreSQL and can be grouped into user-defined sections. The database migration to schema version 4 creates the bookmarks table automatically. + +## 0.2.19 + +Todo markers are case-insensitive. `todo(...)`, `Todo(...)` and `TODO(...)` are all indexed and rendered as todo items. Database migration 4 -> 5 rebuilds the todo index for existing pages so already-saved mixed-case markers become visible without re-saving the pages. + +Editors can start section editing from the small edit link beside a heading in the page contents. The whole page is still saved as one version; section edit only opens the editor at the selected heading. + +Pages whose slug starts with `template-` are available in the editor Template dropdown. Selecting a template copies that page's Markdown into the current editor. Existing non-empty content is only replaced after confirmation. + + + +## 0.2.20 + +Inline `todo(...)` markers render as a yellow `Todo: text` link. Clicking the marker opens the Todo view at the matching item and highlights it. Todo markers inside fenced code blocks remain untouched. diff --git a/info.rkt b/info.rkt index f9d4017..0911107 100644 --- a/info.rkt +++ b/info.rkt @@ -1,7 +1,7 @@ #lang info (define pkg-authors '(hnmdijkema)) -(define version "0.2.15") +(define version "0.2.21") (define license 'MIT) (define collection "racket-wiki") (define pkg-desc diff --git a/private/migrations.rkt b/private/migrations.rkt index 7aa9b82..a2a4df2 100644 --- a/private/migrations.rkt +++ b/private/migrations.rkt @@ -11,7 +11,7 @@ database-schema-version migrate-database!) -(define current-schema-version 3) +(define current-schema-version 5) (define schema-1-statements (list @@ -215,6 +215,30 @@ SQL (replace-page-todos! db (vector-ref row 0) (vector-ref row 1))) (record-schema-version! db 3)) + +(define (migrate-3->4! db) + (query-exec db + #<5! db) + (for ((row (in-list (query-rows db "SELECT id, markdown FROM pages WHERE archived = FALSE")))) + (replace-page-todos! db (vector-ref row 0) (vector-ref row 1))) + (record-schema-version! db 5)) + + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; goal : Bring a racket-wiki PostgreSQL database to the current schema. ; pre : db is a writable PostgreSQL connection and config identifies the @@ -235,6 +259,12 @@ SQL (define after-attachments (database-schema-version db)) (when (= after-attachments 2) (migrate-2->3! db)) + (define after-todos (database-schema-version db)) + (when (= after-todos 3) + (migrate-3->4! db)) + (define after-bookmarks (database-schema-version db)) + (when (= after-bookmarks 4) + (migrate-4->5! db)) (define resulting-version (database-schema-version db)) (when (> resulting-version current-schema-version) (error 'migrate-database! diff --git a/private/storage.rkt b/private/storage.rkt index 304bd49..299d02f 100644 --- a/private/storage.rkt +++ b/private/storage.rkt @@ -22,6 +22,10 @@ read-version search-pages list-todos + list-recent-pages + list-bookmarks + set-bookmark! + delete-bookmark! save-upload! uploaded-file) @@ -390,6 +394,112 @@ SQL 'line (vector-ref row 3) 'text (vector-ref row 4)))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; goal : List recently edited current wiki pages. +; pre : PostgreSQL schema 1 or newer is initialized. +; post : Page rows have only been read. +; result : At most limit page metadata hashes, newest first. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +(define (list-recent-pages config [limit 50]) + (call-with-wiki-database + config + (λ (db) + (for/list ((row (in-list + (query-rows db + (string-append "SELECT " page-columns + " FROM pages WHERE archived = FALSE" + " ORDER BY updated_at DESC, lower(title), title" + " LIMIT $1") + limit)))) + (row->page row #f))))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; goal : List bookmarks for one wiki user. +; pre : PostgreSQL schema 4 or newer is initialized and user-id identifies a user. +; post : Bookmark and page rows have only been read. +; result : Bookmarks ordered by section and position. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +(define (list-bookmarks config user-id) + (call-with-wiki-database + config + (λ (db) + (for/list ((row (in-list + (query-rows db + #<