include

package
v0.2.2 Latest Latest
Warning

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

Go to latest
Published: May 9, 2026 License: MIT Imports: 9 Imported by: 0

Documentation

Overview

Package include resolves and slices files referenced by the `include="..."` fence-block attribute in tinkerdown markdown.

The package is intentionally small: it does not concern itself with HTML rendering, syntax highlighting, or the markdown AST — those stay in parser.go. Three helpers do the work:

  • Resolve confines a relative include path to a discovery root, so authors can't escape with "../../etc/passwd".
  • Slice reads the resolved file and returns either the whole text or a 1-indexed inclusive line range, clamping the end to the file's actual length when the author's range overruns.
  • Dedent strips the common leading whitespace across non-blank lines, so a snippet pulled from inside a function body renders without stray indentation.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Dedent

func Dedent(text string) string

Dedent strips the longest common leading whitespace across all non-blank lines, preserving the relative indentation of the snippet. Blank lines are ignored when computing the prefix and also stripped of leading whitespace in the output.

func FindRegion

func FindRegion(absPath, name string) (start, end int, err error)

FindRegion scans absPath for the named-region markers `>>> region:NAME` (start) and `<<< region:NAME` (end), and returns the 1-indexed inclusive [start, end] line range of the content strictly between them. The markers themselves are excluded.

Markers can be wrapped in any single-line comment style — the matcher only looks for the literal `>>> region:NAME` / `<<< region:NAME` substring on a line, so:

// >>> region:state          // Go / C-family
# >>> region:state           # Python / shell / yaml
<!-- >>> region:state -->    HTML

all work. Errors when either marker is missing or appears in the wrong order.

func LanguageEllipsis

func LanguageEllipsis(lang string) string

LanguageEllipsis returns the comment-style ellipsis line that fits the named fence language — Prism will syntax-highlight it as a proper comment so it visually separates joined ranges without breaking the surrounding code's style.

func Preprocess

func Preprocess(content []byte, baseDir, root string) ([]byte, []string, []string)

Preprocess scans content for fenced code blocks whose fence info contains `include="..."`, replaces the (empty) fence body with the resolved file slice, and returns the transformed content plus the absolute paths of every included file (for the watcher to track) plus any warnings (bad path, missing file, range error). Bad includes pass through with the original empty body so the page still renders — same posture as the embed-lvt unavailable badge.

func PreprocessWithLinks(content []byte, baseDir, root string, link LinkOptions) ([]byte, []string, []string)

PreprocessWithLinks behaves like Preprocess but also appends a "View on GitHub" footer link below each substituted block when link options are provided.

func Resolve

func Resolve(baseDir, root, includePath string) (string, error)

Resolve canonicalizes an include path supplied in markdown. It resolves relative paths against baseDir (the directory of the markdown file), then ensures the result lives inside root (the page-discovery root) so traversal attacks are rejected.

Symlinks are followed on both candidate and root before the containment check so a symlinked tempdir (e.g. macOS /tmp → /private/tmp) doesn't false-positive as an escape.

func Slice

func Slice(absPath, lineRange string) (string, error)

Slice reads absPath and returns either its full content (when lineRange is empty) or the 1-indexed inclusive [start, end] range. Multiple comma-separated ranges are supported (e.g. "5-8,15-22"); they're joined with a single blank line. To insert an ellipsis comment between joined ranges, use SliceRanges with a non-empty separator instead.

The end of each range is clamped to the file's actual line count so a stale range that overruns produces a useful snippet rather than an error. The start must be in-range.

Trailing newlines from the source file are preserved on full-file reads but stripped from sliced ranges, so the rendered code block doesn't end with a stray blank line.

func SliceRanges

func SliceRanges(absPath, lineRange, separator string) (string, error)

SliceRanges is Slice with an explicit separator inserted between joined ranges. Useful for multi-range includes — pass LanguageEllipsis(lang) to get a syntax-highlighted "// ..." line (or its language equivalent) between ranges.

Types

type LinkOptions

type LinkOptions struct {
	RepoURL        string
	Branch         string
	PagePathInRepo string // forward-slash-separated, no trailing slash; e.g. "docs/guides"
}

LinkOptions configures the optional "View on GitHub →" footer that Preprocess appends to each substituted block. When RepoURL is empty or any of the path-derivation inputs are missing, the footer is omitted gracefully. Branch defaults to "main" when unset.

Example for examples/literate-counter-include/index.md including ./_app/counter.go: with RepoURL="https://github.com/foo/bar", Branch="main", PagePathInRepo="examples/literate-counter-include", the footer href becomes

https://github.com/foo/bar/blob/main/examples/literate-counter-include/_app/counter.go#L13-L35

Jump to

Keyboard shortcuts

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