mdrender

package
v0.13.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 7, 2026 License: MIT Imports: 6 Imported by: 0

Documentation

Overview

Package mdrender is the Markdown subset renderer the site publishes the repository's prose through, and the one answer to what that subset refuses.

It is a leaf — it imports only core/mdrecord, for the fence reading its block walk shares with every other record reader — because two kinds of caller need it. The site (core/site) renders every page through it. And the writers of append-only record prose ask it, before they write, whether the site will render what they are about to write: core/site imports the record families that hold such prose, so they could not import it back, and a second copy of the renderer's rules in each writer is a copy that drifts from the renderer (iss-2608301646046226). RefusalIn is that question.

Index

Constants

This section is empty.

Variables

View Source
var HeadingRe = regexp.MustCompile(`^(#{1,6})\s+(.*)$`)

HeadingRe matches an ATX heading at column 0, capturing its marker run and its title. The site's section walk and this renderer's heading block read one pattern, so what the walk splits on is what the renderer renders.

View Source
var (
	OrderedItemRe = regexp.MustCompile(`^(\d+)[.)]\s+(.*)$`)
)
View Source
var VoidElements = map[string]bool{
	"area": true, "base": true, "br": true, "col": true, "embed": true, "hr": true,
	"img": true, "input": true, "link": true, "meta": true, "source": true,
	"track": true, "wbr": true,
}

VoidElements are the HTML elements that never carry a closing tag, so their bare form is still markup.

Functions

func Clip

func Clip(s string) string

Clip shortens a fragment for an error message.

It counts RUNES, because the record is written in prose that carries em-dashes and accents: slicing by bytes lands mid-character and puts a replacement glyph in the middle of the one message somebody reads to find the line the build refused.

func EscapeAttr

func EscapeAttr(s string) string

EscapeAttr escapes an attribute value.

func EscapeText

func EscapeText(s string) string

EscapeText escapes a text node.

func ExecutableScheme

func ExecutableScheme(href string) (string, bool)

ExecutableScheme reports whether an href names a scheme that executes rather than navigates. Escaping an attribute is not enough on its own: a perfectly well-formed `javascript:` href needs no quote to break out of, and the site renders text from a repository whose files an outside contributor can edit. The comparison folds case and strips the whitespace and control characters a browser ignores inside a scheme, because those are exactly what a bypass is written with.

func IndentOf

func IndentOf(s string) int

IndentOf counts a line's leading spaces, a tab counting as one.

func IsSpace

func IsSpace(c byte) bool

IsSpace reports whether a byte is markdown whitespace.

func IsUnorderedItem

func IsUnorderedItem(ln string) bool

IsUnorderedItem reports whether a line opens an unordered list item.

func LinkDefinitions

func LinkDefinitions(md string) map[string]string

LinkDefinitions collects a document's link reference definitions — the `[label]: destination "title"` lines the record's older entries keep at the foot of a file and name from the prose above.

They are document-level, and the renderer works a block at a time, so the caller reads them once and hands them to the Renderer. A reference whose definition is missing stays a refusal: the destination is lost either way, and losing it silently is how a dead cross-reference survives review.

func OpensFence

func OpensFence(blk Block) bool

OpensFence reports whether a block the walk cut opens with a fence this renderer renders as a command block: a three-backtick run at the left margin that opens a fence by mdrecord's rule.

func Quote

func Quote(s string) string

func RefusalIn

func RefusalIn(block string) error

RefusalIn reports the first construct this renderer refuses in one block of record prose — a grounds entry's bullet is one — or nil when the block renders. The error names the construct and why it is refused. It is the renderer itself, run over the block, so what it refuses is exactly what a page build refuses and there is no list of rules to keep in step with it.

Two things a page supplies are absent, and each is answered the strict way, so the answer is never looser than the page the block lands on:

  • The block is judged as part of a document that DEFINES link references. A page that defines none shows `[text][label]` as the brackets it is, while a page that defines any refuses a label it does not define; the record a block is appended to may do either, so every reference link is refused. The one definition carries a label no reference can spell, since a label is folded to trimmed, single-spaced text before it is looked up.
  • Every image is refused. A page resolves a local image against its own committed assets and refuses a remote one; one block of prose has no page to resolve against, and a picture is not what such prose is for.

Types

type Block

type Block struct {
	Text string
	// Line is the 1-based source line the block starts at.
	Line int
}

Block is one top-level markdown block: a paragraph, a table, a fence, an image line, a list, or a blockquote — whatever sits between two blank lines.

func Blocks

func Blocks(md string, start int) []Block

Blocks splits a section body into its top-level blocks, honouring fenced code by mdrecord's ListNested rule, the same reading Sections takes. start is the 1-based source line the body begins at.

type Labels

type Labels struct {
	Copy   string
	Copied string
}

Labels are the interface strings a rendered page carries from the renderer.

type Renderer

type Renderer struct {
	// Labels are the two interface strings the renderer adds — a fenced block's
	// copy button and its confirmation — and it adds nothing else. The site
	// takes them from its closed allowlist of interface strings.
	Labels Labels
	// Image renders one image reference. src is as written in the markdown,
	// relative to the page; alt is its alt text.
	Image func(src, alt string, at Source) (string, error)
	// Link rewrites one href. It never fails: an href it does not recognise is
	// left exactly as the record wrote it.
	Link func(href string, at Source) string
	// Refs are the document's link reference definitions, from LinkDefinitions.
	// A nil map means the document defines none, and every reference link in it
	// is a refusal.
	Refs map[string]string
}

Renderer turns the markdown subset into the site's HTML. Its two hooks are the places the site differs from a generic renderer: an image becomes a committed asset (inlined SVG or copied raster) rather than a bare <img>, and a repo-relative link becomes a site route.

func (*Renderer) Inline

func (r *Renderer) Inline(at Source, s string) (string, error)

Inline renders the span-level subset in two passes.

The first pass reads left to right and finishes everything whose boundaries are unambiguous — escapes, code spans, autolinks, images, links — leaving the emphasis delimiters as unspent runs. The second pass matches those runs.

The order is what makes `**`+"`"+`.abcd/**`+"`"+` stays**` render: a code span binds tighter than emphasis in every reader, so the asterisks inside one are content, and a single left-to-right pass that met the `**` first would take its closer from inside the code and then refuse an unclosed span.

func (*Renderer) RenderBlock

func (r *Renderer) RenderBlock(path string, blk Block) (string, error)

RenderBlock renders one top-level block.

func (*Renderer) RenderBlocks

func (r *Renderer) RenderBlocks(path string, blocks []Block) (string, error)

RenderBlocks renders a block sequence in order.

type Source

type Source struct {
	Path string
	Line int
}

Source is a position in a repository file.

type UnsupportedError

type UnsupportedError struct {
	Path      string
	Line      int
	Construct string
	Detail    string
}

UnsupportedError is a markdown construct outside the rendered subset.

func (*UnsupportedError) Error

func (e *UnsupportedError) Error() string

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL