summaryrefslogtreecommitdiffstats
path: root/internal/builder/markdown.go
diff options
context:
space:
mode:
authorClaude <noreply@anthropic.com>2026-03-31 12:11:18 +0200
committerClaude <noreply@anthropic.com>2026-03-31 12:11:18 +0200
commit3cb7c82cf7c4e050148f69be23590a7fbe587a27 (patch)
treed2b6506db2de72b3a6982cfbe69925b88936de90 /internal/builder/markdown.go
parent33f214f6cd9729473bb55fd7b3b923d5d960bb98 (diff)
downloadnebbet.no-3cb7c82cf7c4e050148f69be23590a7fbe587a27.tar.xz
nebbet.no-3cb7c82cf7c4e050148f69be23590a7fbe587a27.zip
Add static site builder: SQLite-backed MD→HTML pipeline
- cmd/nebbet: CLI with build [--watch] and user add/passwd/delete/list - internal/builder: markdown→HTML, component injection via HTML comments, auto importmap from lib/, fsnotify watch with 150ms debounce - internal/db: meta.db (page index, tag queries) + search.db (FTS5) - internal/sqlitedrv: minimal CGO database/sql driver for system libsqlite3 - internal/auth: htpasswd-compatible bcrypt password file management - templates/base.html + admin.html, styles/main.css + admin.css - nginx.conf with auth_basic for /admin, clean URLs, gzip - nebbet.service systemd unit for watch daemon - Example content/index.md and components/site-greeting.js https://claude.ai/code/session_01HTc1BCBCiMTEB54XQP1Wz9
Diffstat (limited to 'internal/builder/markdown.go')
-rw-r--r--internal/builder/markdown.go49
1 files changed, 49 insertions, 0 deletions
diff --git a/internal/builder/markdown.go b/internal/builder/markdown.go
new file mode 100644
index 0000000..4e00ca3
--- /dev/null
+++ b/internal/builder/markdown.go
@@ -0,0 +1,49 @@
+package builder
+
+import (
+ "bytes"
+ "regexp"
+ "strings"
+
+ "github.com/yuin/goldmark"
+ "github.com/yuin/goldmark/extension"
+ "github.com/yuin/goldmark/parser"
+ "github.com/yuin/goldmark/renderer/html"
+)
+
+var md = goldmark.New(
+ goldmark.WithExtensions(
+ extension.GFM,
+ extension.Table,
+ extension.Strikethrough,
+ extension.TaskList,
+ ),
+ goldmark.WithParserOptions(
+ parser.WithAutoHeadingID(),
+ ),
+ goldmark.WithRendererOptions(
+ // Allow raw HTML pass-through so component tags survive round-trip.
+ html.WithUnsafe(),
+ ),
+)
+
+// MarkdownToHTML converts a markdown string to an HTML fragment.
+func MarkdownToHTML(body string) (string, error) {
+ var buf bytes.Buffer
+ if err := md.Convert([]byte(body), &buf); err != nil {
+ return "", err
+ }
+ return buf.String(), nil
+}
+
+var (
+ htmlTagRe = regexp.MustCompile(`<[^>]+>`)
+ multiSpaceRe = regexp.MustCompile(`\s+`)
+)
+
+// StripHTML removes HTML tags and normalises whitespace for search indexing.
+func StripHTML(h string) string {
+ plain := htmlTagRe.ReplaceAllString(h, " ")
+ plain = multiSpaceRe.ReplaceAllString(plain, " ")
+ return strings.TrimSpace(plain)
+}