JSON canvas initial

This commit is contained in:
2026-09-22 21:28:28 +02:00
parent 7b451bae86
commit b48d476b39
21 changed files with 3159 additions and 7 deletions
+39
View File
@@ -64,6 +64,39 @@ type pageData struct {
SidebarWidget template.HTML
SuppressTOC bool
RenderMS int64
// Canvases lists every .canvas file in this folder as a view-switcher tab.
// ActiveCanvas names the one currently being viewed ("" on a normal page),
// and is what makes this page render as a canvas rather than as markdown.
Canvases []canvasRef
ActiveCanvas string
// CanvasJSON is the whole canvas document plus its server-rendered node
// HTML, inlined into the page so opening a canvas costs one request.
CanvasJSON template.JS
// CanvasError carries a parse/validation failure to the template, which
// shows it in place of the canvas instead of failing the request.
CanvasError string
}
// layoutData is the contract every view built on assets/layout.html satisfies.
// The layout is shared by pageData and searchPageData, and a method only one of
// them has fails at render time with a half-written response rather than at
// build time — so each is asserted against the interface here.
type layoutData interface {
ShowPageChrome() bool
}
var (
_ layoutData = pageData{}
_ layoutData = searchPageData{}
)
// ShowPageChrome reports whether the standard page furniture — search box,
// folder-tree rail, right sidebar, and the collapsed ACTIONS dropdown — should
// render. The editor and the canvas view both take the full width and supply
// their own controls, so both opt out.
func (d pageData) ShowPageChrome() bool {
return !d.EditMode && d.ActiveCanvas == ""
}
// Allowed values for the listing view settings. Unknown values in the file or
@@ -130,6 +163,7 @@ var (
iconAudio = readIcon("audio")
iconArchive = readIcon("archive")
iconGeneric = readIcon("generic")
iconCanvas = readIcon("canvas")
)
// renderMarkdown converts raw markdown to trusted HTML.
@@ -211,6 +245,9 @@ func listEntries(fsPath, urlPath, sortKey, order string) []entry {
if name == "index.md" {
continue // rendered above, don't list it
}
if isCanvasFile(name) {
continue // surfaced as a view-switcher tab above the content
}
f := entry{
Icon: fileIcon(name),
Name: name,
@@ -300,6 +337,8 @@ func readIcon(name string) template.HTML {
func fileIcon(name string) template.HTML {
ext := strings.ToLower(path.Ext(name))
switch ext {
case ".canvas":
return iconCanvas
case ".md", ".pdf":
return iconDoc
case ".png", ".jpg", ".jpeg", ".gif", ".webp", ".svg":