Documentation
¶
Overview ¶
Package tinkerdown provides the core library for building interactive documentation with markdown files and embedded executable code blocks.
Index ¶
- Variables
- func ParseMarkdown(content []byte) (*Frontmatter, []*CodeBlock, string, error)
- func ParseMarkdownWithPartials(content []byte, baseDir string, allowRawHTML bool) (*Frontmatter, []*CodeBlock, string, error)
- func ParseTimeout(s string) time.Duration
- func ProcessEmbedLvt(htmlStr string, req *http.Request) string
- func ProcessPartials(content []byte, baseDir string, seen map[string]bool) ([]byte, error)
- func SetMermaidRenderer(r DiagramRenderer)
- type Action
- type BlocksConfig
- type ChartOptions
- type CodeBlock
- type DiagramRenderer
- type EmbedRoute
- type FeaturesConfig
- type Frontmatter
- type InteractiveBlock
- type MessageEnvelope
- type MessageRouter
- type Page
- type PageConfig
- type PageState
- type ParamDef
- type ParseError
- type PersistMode
- type ResponseEnvelope
- type ServerBlock
- type SourceConfig
- type StatusType
- type StylingConfig
- type Tab
- type WasmBlock
Constants ¶
This section is empty.
Variables ¶
var DefaultSourceRef string
DefaultSourceRef is the git ref used to construct GitHub source links from `LANG include="..."` blocks when the page's frontmatter doesn't pin one explicitly via `source_ref`. The tinkerdown binary sets this at startup to its build-time version (via `cmd/tinkerdown/main.go`'s ldflags-injected version), so released docs always link at the matching tag.
For `dev` builds (no ldflags) and library callers that don't set it, the fallback in renderSourceFooter resolves to "main".
Concurrency contract: this is a single-writer, set-once-at-startup global. Production code only writes it before any goroutines start, during main() init. Tests must not mutate it from parallel test bodies — if a test needs a different ref, pass it through the page's frontmatter `source_ref` field instead.
Functions ¶
func ParseMarkdown ¶
func ParseMarkdown(content []byte) (*Frontmatter, []*CodeBlock, string, error)
ParseMarkdown parses a markdown file and extracts frontmatter and code blocks. Treats the input as trusted (file-based) content — raw HTML in the markdown body is preserved. For untrusted input use ParseMarkdownWithPartials with allowRawHTML=false.
func ParseMarkdownWithPartials ¶
func ParseMarkdownWithPartials(content []byte, baseDir string, allowRawHTML bool) (*Frontmatter, []*CodeBlock, string, error)
ParseMarkdownWithPartials parses markdown with partial file support. baseDir is used to resolve relative paths in {{partial "file.md"}} directives.
allowRawHTML controls whether <script>, <iframe>, etc. in the markdown body pass through to the rendered output. Pass true for trusted file-based or programmatic content; pass false when the input came from a user (playground via ParseString). See newGoldmarkParser for the threat-model rationale.
func ParseTimeout ¶ added in v0.2.0
ParseTimeout parses a duration string like "2s" / "1500ms" and returns the duration; falls back to defaultEmbedTimeout for empty or invalid input. Exported so other tinkerdown packages (e.g. tests, future proxy integration) can share the same parsing rules.
func ProcessEmbedLvt ¶ added in v0.2.0
ProcessEmbedLvt scans rendered page HTML for `embed-lvt` placeholders and replaces each with the wrapper HTML returned by the upstream LiveTemplate app. Forwards the docs reader's Cookie and Accept-Language headers so cookie-based auth keeps working when apps share a cookie domain.
On error or timeout, the placeholder becomes a small "live demo unavailable" badge and the page renders without the embed.
Same-origin embeds (path-only, no `server` attribute) resolve against the request's host so the docs site can embed apps proxied through itself with zero CORS or origin configuration.
func ProcessPartials ¶
ProcessPartials recursively processes {{partial "file.md"}} directives in content. baseDir is the directory to resolve relative paths from. seen tracks already-included files to prevent circular dependencies.
func SetMermaidRenderer ¶ added in v0.1.3
func SetMermaidRenderer(r DiagramRenderer)
SetMermaidRenderer registers a renderer that will be used to pre-render ```mermaid fenced blocks during ParseMarkdown. Pass nil to disable. Safe to call once during server initialization.
Types ¶
type Action ¶
type Action struct {
Kind string `yaml:"kind"` // Action kind: "sql", "http", "exec"
Source string `yaml:"source,omitempty"` // For sql: source name to execute against
Statement string `yaml:"statement,omitempty"` // For sql: SQL statement with :param placeholders
URL string `yaml:"url,omitempty"` // For http: request URL (supports template expressions)
Method string `yaml:"method,omitempty"` // For http: HTTP method (default: POST)
Body string `yaml:"body,omitempty"` // For http: request body template
Cmd string `yaml:"cmd,omitempty"` // For exec: command to run
Params map[string]ParamDef `yaml:"params,omitempty"` // Parameter definitions
Confirm string `yaml:"confirm,omitempty"` // Confirmation message (triggers dialog)
}
Action defines a custom action that can be triggered via button name routing or lvt-on:click.
type BlocksConfig ¶
type BlocksConfig struct {
AutoID bool `yaml:"auto_id"`
IDFormat string `yaml:"id_format"`
ShowLineNumbers bool `yaml:"show_line_numbers"`
}
BlocksConfig represents code block display configuration.
type ChartOptions ¶
type ChartOptions struct {
Colors []string `yaml:"colors,omitempty" json:"colors,omitempty"`
Stacked bool `yaml:"stacked,omitempty" json:"stacked,omitempty"`
Horizontal bool `yaml:"horizontal,omitempty" json:"horizontal,omitempty"`
Legend *bool `yaml:"legend,omitempty" json:"legend,omitempty"`
}
ChartOptions holds per-chart customization from frontmatter.
type CodeBlock ¶
type CodeBlock struct {
Type string // "server", "wasm", "lvt"
Language string // "go", etc.
Flags []string // "readonly", "editable"
Metadata map[string]string // id, state, etc.
Content string
Line int // Line number in source file
}
CodeBlock represents a code block extracted from markdown.
type DiagramRenderer ¶ added in v0.1.3
DiagramRenderer renders diagram source to bytes (typically inline SVG). The interface deliberately mirrors internal/diagrams.Renderer so the concrete implementation can live in that subpackage without forcing callers of tinkerdown to import it.
type EmbedRoute ¶ added in v0.2.0
EmbedRoute pairs a docs-side path with an upstream HTTP origin. The server registers a reverse-proxy at `Path` forwarding to `Upstream` for both HTTP and WebSocket upgrades, so the embed-lvt block's browser-side connection can reach the deployed app via the docs origin.
type FeaturesConfig ¶
type FeaturesConfig struct {
HotReload bool `yaml:"hot_reload"`
Sidebar bool `yaml:"sidebar"` // Show navigation sidebar
}
FeaturesConfig represents feature flags.
type Frontmatter ¶
type Frontmatter struct {
// Page metadata
Title string `yaml:"title"`
Description string `yaml:"description,omitempty"` // Used for <meta name="description"> + og:description
Image string `yaml:"image,omitempty"` // Path/URL used for og:image (falls back to site logo)
Type string `yaml:"type"` // tutorial, guide, reference, playground
Persist PersistMode `yaml:"persist"` // none, localstorage, server
Steps int `yaml:"steps"`
// Top-level convenience options
Sidebar *bool `yaml:"sidebar,omitempty"` // Show navigation sidebar (overrides features.sidebar)
// Layout selects the page shell. "" or "docs" (default) renders the full
// docs chrome (sidebar, breadcrumbs, opinionated typography). "landing"
// renders a minimal full-bleed shell for bespoke marketing pages — no
// sidebar, no content-wrapper clamp, no docs typography — while still
// loading the client JS (so embed-lvt demos work) and any styling.custom_css.
// Unknown values fall back to the docs layout.
Layout string `yaml:"layout,omitempty"`
// LvtShowSource toggles the page-level default for ` “`lvt ` block source
// display. When true, every ` “`lvt ` block on the page renders both its
// template source as a syntax-highlighted code listing AND the live
// interactive widget. Per-block `show-source` / `hide-source` flags
// override this default. Defaults to nil/false to preserve existing
// behavior — opt-in for documentation pages.
LvtShowSource *bool `yaml:"lvt_show_source,omitempty"`
// Source provenance — used to render an "Edit this page" link that
// points at the canonical source file in its origin repo. Useful when
// a page was synced from another repo and the docs site is not the
// canonical home of the content. Both default to "" (use site-level
// repository + the page's own relative path).
SourceRepo string `yaml:"source_repo,omitempty"` // e.g. "https://github.com/livetemplate/livetemplate"
SourcePath string `yaml:"source_path,omitempty"` // e.g. "docs/guides/progressive-complexity.md"
// SourceRef pins the git ref used in include source-link footers
// (tag/branch/commit). Resolution order: this field if set;
// otherwise tinkerdown.DefaultSourceRef (populated from the
// binary's release version by cmd/tinkerdown/main.go); otherwise
// "main".
SourceRef string `yaml:"source_ref,omitempty"`
// SourceCommit records the exact upstream commit at sync time. It is
// displayed as provenance in site chrome when present.
SourceCommit string `yaml:"source_commit,omitempty"`
// Chart customization (keyed by heading slug)
Charts map[string]ChartOptions `yaml:"charts,omitempty"`
// Config options (can override livemdtools.yaml)
Sources map[string]SourceConfig `yaml:"sources,omitempty"`
Actions map[string]Action `yaml:"actions,omitempty"`
Styling *StylingConfig `yaml:"styling,omitempty"`
Blocks *BlocksConfig `yaml:"blocks,omitempty"`
Features *FeaturesConfig `yaml:"features,omitempty"`
// Computed expressions found in the markdown content (populated during parsing)
// Map of expression ID to expression string (e.g., "expr-1" -> "count(tasks where done)")
Expressions map[string]string `yaml:"-"`
// Schedule tokens found in the markdown content (populated during parsing)
Schedules []*schedule.Token `yaml:"-"`
// Imperative commands (Notify, Run action) found in the markdown (populated during parsing)
Imperatives []*schedule.Imperative `yaml:"-"`
// Schedule parsing warnings (populated during parsing)
ScheduleWarnings []schedule.ParseWarning `yaml:"-"`
// HasCharts indicates the page has {chart:...} annotations (populated during parsing)
HasCharts bool `yaml:"-"`
// HasMermaid indicates the page has “`mermaid fenced blocks (populated during parsing)
HasMermaid bool `yaml:"-"`
}
Frontmatter represents the YAML frontmatter at the top of a markdown file.
type InteractiveBlock ¶
type InteractiveBlock struct {
ID string
StateRef string // References a ServerBlock ID
Template *livetemplate.Template
Store interface{} // State object with action methods (uses method dispatch)
Content string // Template content
Metadata map[string]string
}
InteractiveBlock represents a live UI component powered by server state. Each block is a mini livetemplate instance.
type MessageEnvelope ¶
type MessageEnvelope struct {
BlockID string `json:"blockID"`
Action string `json:"action"`
Data json.RawMessage `json:"data"`
}
MessageEnvelope wraps messages with block ID routing information.
type MessageRouter ¶
type MessageRouter struct {
// contains filtered or unexported fields
}
MessageRouter routes messages to appropriate blocks based on blockID.
func NewMessageRouter ¶
func NewMessageRouter(ps *PageState) *MessageRouter
NewMessageRouter creates a new message router for a page state.
func (*MessageRouter) Route ¶
func (mr *MessageRouter) Route(envelope *MessageEnvelope) (*ResponseEnvelope, error)
Route routes an incoming message to the appropriate handler.
type Page ¶
type Page struct {
ID string
Title string
Description string // From frontmatter; used for <meta description> + og:description
Image string // From frontmatter; used for og:image
Type string // tutorial, guide, reference, playground
SourceFile string // Absolute path to source .md file (for error messages)
SourceRepo string // Origin GitHub repo URL from frontmatter (for edit link)
SourcePath string // Path within origin repo from frontmatter (for edit link)
SourceRef string // Git ref from frontmatter, when known
SourceCommit string // Immutable source commit from frontmatter, when known
Sidebar *bool // nil = use default, true/false = explicit override
Layout string // From frontmatter; "" / "docs" = default shell, "landing" = minimal full-bleed shell
Config PageConfig
StaticHTML string
ServerBlocks map[string]*ServerBlock
WasmBlocks map[string]*WasmBlock
InteractiveBlocks map[string]*InteractiveBlock
// Expressions maps expression IDs to expression strings (e.g., "expr-0" -> "count(tasks where done)")
// These are computed expressions found in inline code spans like `=count(tasks where done)`
Expressions map[string]string
// Schedules contains parsed schedule tokens found in the markdown content
Schedules []*schedule.Token
// Imperatives contains parsed imperative commands (Notify, Run action) from the markdown
Imperatives []*schedule.Imperative
// ScheduleWarnings contains any warnings generated during schedule parsing
ScheduleWarnings []schedule.ParseWarning
// HasCharts indicates the page has chart annotations requiring Chart.js
HasCharts bool
// HasMermaid indicates the page contains “`mermaid fenced blocks
// requiring the Mermaid runtime (~3.3MB). Used by the server to
// conditionally inject the script and avoid penalising pages without
// any diagrams.
HasMermaid bool
// EmbedRoutes is the set of (path, upstream) pairs declared by
// ` “`embed-lvt path="..." upstream="..." ` blocks on this page.
// The server walks every page after Discover() and turns these into
// auto-registered reverse-proxy routes, so authors don't have to
// duplicate the upstream coordinates in tinkerdown.yaml.
EmbedRoutes []EmbedRoute
// IncludedFiles holds the absolute paths of files referenced by
// ` “`LANG include="..." ` fences on this page. The watcher uses
// this list to broadcast a reload when any included file changes,
// so docs stay in sync with the real source they cite.
IncludedFiles []string
}
Page represents a parsed tinkerdown tutorial/guide/playground.
func BuildPage ¶
BuildPage creates a Page from raw content with a specified ID and source file. This is useful for testing and programmatic page creation. The content should be valid markdown with optional frontmatter.
Treats input as trusted (programmatic/test callers control the content) — raw HTML in the markdown body is preserved.
func ParseFile ¶
ParseFile parses a markdown file and creates a Page. Includes (`include="..."` fence attributes) are confined to the markdown file's own directory tree.
To allow includes to reach files elsewhere within a site (e.g. a recipes/ page citing a shared `_app/` directory), use ParseFileInSite — which widens the include-confinement root to the site directory while still rejecting paths that escape it.
func ParseFileInSite ¶ added in v0.2.1
ParseFileInSite parses a markdown file as part of a multi-page site rooted at siteRoot. Includes (`include="..."`) may reference files anywhere within siteRoot, not just the page's own directory subtree; paths that would escape siteRoot are still rejected.
`path` must be located within siteRoot (otherwise every include — including local ones in the page's own directory — would fail confinement against a root that isn't an ancestor of the page). This is enforced upfront with a clear error rather than producing confusing per-include warnings later.
This is the entry point used by `tinkerdown serve` so cross-page references like include="../recipes/counter/_app/counter.go" resolve correctly. Library callers that don't want the wider scope (e.g. rendering a single standalone .md file) should use ParseFile.
If siteRoot is empty, behaves identically to ParseFile (no path-under-root check).
func ParseString ¶
ParseString parses markdown content from a string and creates a Page. This is useful for the playground where content comes from user input. Raw HTML in the body is omitted to prevent XSS — playground submissions are untrusted.
func (*Page) ParseFiles ¶
ParseFiles parses markdown files and updates the Page.
type PageConfig ¶
type PageConfig struct {
// Page behavior
Persist PersistMode
MultiStep bool
StepCount int
// Effective config (merged from frontmatter + site config)
Sources map[string]SourceConfig
Actions map[string]Action
Styling StylingConfig
Blocks BlocksConfig
Features FeaturesConfig
}
PageConfig contains configuration for a page.
func (*PageConfig) MergeFromFrontmatter ¶
func (pc *PageConfig) MergeFromFrontmatter(fm *Frontmatter)
MergeFromFrontmatter applies frontmatter config options to PageConfig. Frontmatter values take precedence over any existing values.
type PageState ¶
type PageState struct {
// Current step for multi-step tutorials
CurrentStep int
// Interactive block states (stored as generic interfaces)
// State objects use method dispatch for action handling
InteractiveStates map[string]interface{}
// Code edits for WASM blocks (blockID -> code)
CodeEdits map[string]string
// Completed steps tracking
CompletedSteps []int
// contains filtered or unexported fields
}
PageState manages the runtime state of a livemdtools session.
func NewPageState ¶
NewPageState creates a new page state for a session.
type ParamDef ¶
type ParamDef struct {
Type string `yaml:"type,omitempty"` // Parameter type: "string", "number", "date", "bool"
Required bool `yaml:"required,omitempty"` // Whether the parameter is required
Default string `yaml:"default,omitempty"` // Default value
}
ParamDef defines a parameter for an action.
type ParseError ¶
type ParseError struct {
File string // Source file path
Line int // Line number (1-indexed)
Column int // Column number (1-indexed, optional)
Message string // Error message
Code string // Offending code snippet
Hint string // Helpful suggestion
Related string // Related information (e.g., "State 'foo' defined at line 20")
}
ParseError represents a detailed parsing error with context.
func NewParseError ¶
func NewParseError(file string, line int, message string) *ParseError
NewParseError creates a new ParseError.
func (*ParseError) Error ¶
func (e *ParseError) Error() string
Error implements the error interface.
func (*ParseError) Format ¶
func (e *ParseError) Format() string
Format returns a nicely formatted error message with context.
func (*ParseError) WithColumn ¶
func (e *ParseError) WithColumn(col int) *ParseError
WithColumn adds column information to the error.
func (*ParseError) WithHint ¶
func (e *ParseError) WithHint(hint string) *ParseError
WithHint adds a helpful hint to the error.
func (*ParseError) WithRelated ¶
func (e *ParseError) WithRelated(related string) *ParseError
WithRelated adds related information to the error.
type PersistMode ¶
type PersistMode string
PersistMode determines how tutorial state is persisted.
const ( PersistNone PersistMode = "none" PersistLocalStorage PersistMode = "localstorage" PersistServer PersistMode = "server" )
type ResponseEnvelope ¶
type ResponseEnvelope struct {
BlockID string `json:"blockID"`
Tree map[string]interface{} `json:"tree,omitempty"`
Meta map[string]interface{} `json:"meta"`
}
ResponseEnvelope wraps responses with block ID routing information.
type ServerBlock ¶
type ServerBlock struct {
ID string
Language string // Currently only "go"
Content string
Metadata map[string]string
}
ServerBlock represents author-written server-side code. This code is trusted, pre-compiled, and powers interactive blocks.
type SourceConfig ¶
type SourceConfig struct {
Type string `yaml:"type"` // exec, pg, rest, csv, json, markdown, sqlite, wasm
Cmd string `yaml:"cmd,omitempty"` // For exec type
Query string `yaml:"query,omitempty"` // For pg type
From string `yaml:"from,omitempty"` // For rest type: API endpoint URL
File string `yaml:"file,omitempty"` // For csv/json/markdown types
Anchor string `yaml:"anchor,omitempty"` // For markdown: section anchor (e.g., "#todos")
DB string `yaml:"db,omitempty"` // For sqlite: database file path
Table string `yaml:"table,omitempty"` // For sqlite: table name
Path string `yaml:"path,omitempty"` // For wasm: path to .wasm file
QueryFile string `yaml:"query_file,omitempty"` // For graphql: path to .graphql file
Variables map[string]interface{} `yaml:"variables,omitempty"` // For graphql: query variables
Headers map[string]string `yaml:"headers,omitempty"` // For rest: HTTP headers (env vars expanded)
QueryParams map[string]string `yaml:"query_params,omitempty"` // For rest: URL query parameters
ResultPath string `yaml:"result_path,omitempty"` // For rest: dot-path to extract array (e.g., "data.items")
Readonly *bool `yaml:"readonly,omitempty"` // For markdown/sqlite: read-only mode (default: true)
Options map[string]string `yaml:"options,omitempty"`
Manual bool `yaml:"manual,omitempty"` // For exec: require Run button click
Format string `yaml:"format,omitempty"` // For exec: output format (json, lines, csv)
Delimiter string `yaml:"delimiter,omitempty"` // For exec CSV: field delimiter (default ",")
Env map[string]string `yaml:"env,omitempty"` // For exec: environment variables (env vars expanded)
Timeout string `yaml:"timeout,omitempty"` // For exec/rest: timeout (e.g., "30s", "1m")
AutoBind *bool `yaml:"auto_bind,omitempty"` // Set to false to exclude from auto-table matching
// For computed sources
GroupBy string `yaml:"group_by,omitempty"` // Field to group by
Aggregate map[string]string `yaml:"aggregate,omitempty"` // Field → aggregation expression
Filter string `yaml:"filter,omitempty"` // Optional filter expression
}
SourceConfig represents a data source configuration for lvt-source blocks.
type StatusType ¶
type StatusType string
StatusType represents the type of status banner
const ( StatusSuccess StatusType = "success" StatusWarning StatusType = "warning" StatusError StatusType = "error" StatusInfo StatusType = "info" )
type StylingConfig ¶
type StylingConfig struct {
Theme string `yaml:"theme"`
PrimaryColor string `yaml:"primary_color"`
Font string `yaml:"font"`
}
StylingConfig represents styling/theme configuration.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
cmd
|
|
|
tinkerdown
command
Command tinkerdown is the CLI tool for creating and serving interactive documentation.
|
Command tinkerdown is the CLI tool for creating and serving interactive documentation. |
|
docs
|
|
|
research/examples/custom-sources/go
command
Change freeze checker for tinkerdown Checks if deploys are allowed based on calendar rules
|
Change freeze checker for tinkerdown Checks if deploys are allowed based on calendar rules |
|
examples
|
|
|
lvt-source-wasm-test/sources
command
Example WASM source module for tinkerdown.
|
Example WASM source module for tinkerdown. |
|
internal
|
|
|
assets
Package assets embeds the client JavaScript, CSS, and vendor libraries
|
Package assets embeds the client JavaScript, CSS, and vendor libraries |
|
blocks
Package blocks provides block type registry and management.
|
Package blocks provides block type registry and management. |
|
cache
Package cache provides caching functionality for data sources.
|
Package cache provides caching functionality for data sources. |
|
diagrams
Package diagrams provides server-side renderers for diagram-as-code blocks (currently mermaid via Kroki) so tinkerdown sites can ship pre-rendered SVGs and skip the heavyweight client-side runtime.
|
Package diagrams provides server-side renderers for diagram-as-code blocks (currently mermaid via Kroki) so tinkerdown sites can ship pre-rendered SVGs and skip the heavyweight client-side runtime. |
|
include
Package include resolves and slices files referenced by the `include="..."` fence-block attribute in tinkerdown markdown.
|
Package include resolves and slices files referenced by the `include="..."` fence-block attribute in tinkerdown markdown. |
|
markdown
Package markdown provides markdown parsing functionality for livemdtools.
|
Package markdown provides markdown parsing functionality for livemdtools. |
|
output
Package output provides notification outputs for tinkerdown.
|
Package output provides notification outputs for tinkerdown. |
|
runtime
Package runtime provides expression evaluation for computed expressions.
|
Package runtime provides expression evaluation for computed expressions. |
|
schedule
Package schedule provides parsing and execution of schedule tokens.
|
Package schedule provides parsing and execution of schedule tokens. |
|
security
Package security provides shared security validation functions.
|
Package security provides shared security validation functions. |
|
server
Package server provides HTTP handlers for the tinkerdown server.
|
Package server provides HTTP handlers for the tinkerdown server. |
|
slug
Package slug provides heading-to-anchor conversion (GitHub-style slugification).
|
Package slug provides heading-to-anchor conversion (GitHub-style slugification). |
|
source
Package source provides data source implementations for lvt-source blocks.
|
Package source provides data source implementations for lvt-source blocks. |
|
state
Package state provides state management for livemdtools.
|
Package state provides state management for livemdtools. |
|
wasm
Package wasm provides WASM-based data source support for tinkerdown.
|
Package wasm provides WASM-based data source support for tinkerdown. |
|
pkg
|
|
|
embedded
Package embedded provides functionality for running tinkerdown apps from embedded filesystems.
|
Package embedded provides functionality for running tinkerdown apps from embedded filesystems. |