From 6b6b5d2e35ff182a0732da245f4eb37c8afa0564 Mon Sep 17 00:00:00 2001 From: grm Date: Wed, 16 Sep 2026 18:37:20 +0300 Subject: Add an HTML mode to posts, page intros and announcements Markdown is the default and unchanged; the editor's new Format switch stores the text as raw HTML instead, put on the blog exactly as written. Like the custom HTML module it is unsanitised on purpose: the escape hatch for embeds, scripts and inline styles that Markdown cannot express. The source column keeps holding the text in both modes and a `format` column says how to read it, so the public templates and the feed still print the stored `*_html`. The dashboard preview of HTML goes into a sandboxed iframe rather than the page, because a superadmin edits other people's blogs and their markup must never run on the dashboard origin. Search snippets of HTML posts are cut from a tag-stripped copy. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01Sd8UPWrvyYCLj97JexNw3A --- cmd/blogspace/seed.go | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'cmd') diff --git a/cmd/blogspace/seed.go b/cmd/blogspace/seed.go index 14c378f..44171a3 100644 --- a/cmd/blogspace/seed.go +++ b/cmd/blogspace/seed.go @@ -124,14 +124,21 @@ func seed(ctx context.Context, cfg *config.Config, st *store.Store) error { posts := []struct { page, title, body string tags []string + html bool // written in HTML mode: stored as is }{ - {"home", "Welcome to my corner of the web", "This is the **first post**. It lives on the home page.\n\nThings I plan to write about:\n\n- tomatoes\n- Go\n- the occasional recipe\n\n![gradient](/media/" + bg.ID.String() + ")\n\nThat image above was uploaded through the dashboard, and here is a file to download: [notes.txt](/media/" + notes.ID.String() + ").", []string{"Go", "tomatoes", "meta"}}, - {"home", "Why I still like plain HTML", "No frameworks, no build step. Just `

` tags and a stylesheet.\n\n> Simplicity is prerequisite for reliability. — Dijkstra\n\n```go\nfunc main() {\n\tfmt.Println(\"hello\")\n}\n```", []string{"Go", "web"}}, - {"news", "Site is up", "The blog is live. Expect sporadic updates.", []string{"meta"}}, - {"news", "Tomato season", "First ripe tomato of the year! Table for the record:\n\n| Variety | Days |\n|---|---|\n| Cherry | 62 |\n| Beefsteak | 85 |", []string{"tomatoes", "garden", "Συνταγές"}}, + {"home", "Welcome to my corner of the web", "This is the **first post**. It lives on the home page.\n\nThings I plan to write about:\n\n- tomatoes\n- Go\n- the occasional recipe\n\n![gradient](/media/" + bg.ID.String() + ")\n\nThat image above was uploaded through the dashboard, and here is a file to download: [notes.txt](/media/" + notes.ID.String() + ").", []string{"Go", "tomatoes", "meta"}, false}, + {"home", "Why I still like plain HTML", "No frameworks, no build step. Just `

` tags and a stylesheet.\n\n> Simplicity is prerequisite for reliability. — Dijkstra\n\n```go\nfunc main() {\n\tfmt.Println(\"hello\")\n}\n```", []string{"Go", "web"}, false}, + {"news", "Site is up", "The blog is live. Expect sporadic updates.", []string{"meta"}, false}, + {"news", "Tomato season", "First ripe tomato of the year! Table for the record:\n\n| Variety | Days |\n|---|---|\n| Cherry | 62 |\n| Beefsteak | 85 |", []string{"tomatoes", "garden", "Συνταγές"}, false}, + {"home", "A post written in HTML", "

This one is raw HTML, not Markdown: the editor's Format switch.

\n\n
Any markup goes — this box has its own inline stylesheet.
\n
And a folding section

Which Markdown alone cannot make.

", []string{"web", "meta"}, true}, } for _, p := range posts { - post := &store.Post{PageID: pages[p.page].ID, Title: p.title, Slug: slug.Make(p.title), BodyMD: p.body, BodyHTML: markdown.Render(p.body), Published: true} + post := &store.Post{PageID: pages[p.page].ID, Title: p.title, Slug: slug.Make(p.title), BodyMD: p.body, Published: true} + if p.html { + post.Format, post.BodyHTML = store.FormatHTML, p.body + } else { + post.Format, post.BodyHTML = store.FormatMarkdown, markdown.Render(p.body) + } created, err := bs.CreatePost(ctx, post) if err != nil { return err -- cgit v1.2.3