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 ¶
- Variables
- func Clip(s string) string
- func EscapeAttr(s string) string
- func EscapeText(s string) string
- func ExecutableScheme(href string) (string, bool)
- func IndentOf(s string) int
- func IsSpace(c byte) bool
- func IsUnorderedItem(ln string) bool
- func LinkDefinitions(md string) map[string]string
- func OpensFence(blk Block) bool
- func Quote(s string) string
- func RefusalIn(block string) error
- type Block
- type Labels
- type Renderer
- type Source
- type UnsupportedError
Constants ¶
This section is empty.
Variables ¶
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.
var (
OrderedItemRe = regexp.MustCompile(`^(\d+)[.)]\s+(.*)$`)
)
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 ¶
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 ExecutableScheme ¶
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 IsUnorderedItem ¶
IsUnorderedItem reports whether a line opens an unordered list item.
func LinkDefinitions ¶
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 ¶
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 RefusalIn ¶
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 ¶
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.
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 ¶
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 ¶
RenderBlock renders one top-level block.
type UnsupportedError ¶
UnsupportedError is a markdown construct outside the rendered subset.
func (*UnsupportedError) Error ¶
func (e *UnsupportedError) Error() string