parse

package
v0.5.0 Latest Latest
Warning

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

Go to latest
Published: Sep 27, 2026 License: Apache-2.0 Imports: 16 Imported by: 0

Documentation

Overview

Package parse turns Markdown files with YAML frontmatter into documents: the frontmatter split, a strict YAML decode, body links and derived edges.

Index

Constants

View Source
const Delimiter = "---"

Delimiter opens and closes a frontmatter block.

Variables

This section is empty.

Functions

func Attr

func Attr(fm map[string]any, key string) (string, bool)

Attr reads a scalar frontmatter value as a string.

func FrontmatterSpan

func FrontmatterSpan(src []byte) (start, end int, ok bool)

FrontmatterSpan reports the byte range of the frontmatter block inside src: start is the first byte after the opening delimiter line, end the first byte of the closing delimiter line. ok is false when src carries no terminated block. Both CRLF and LF line endings delimit a block, so a document authored on Windows is managed like any other.

func KeyLines added in v0.2.0

func KeyLines(src []byte) map[string]int

KeyLines reports the line of every top-level key in a frontmatter block, 1-based and relative to the first line of the block. A block that does not parse has no keys; the decode failure is reported separately.

func LocalPath added in v0.2.0

func LocalPath(base, path string) string

LocalPath rewrites one path the way a caller standing in base would type it.

func Localize added in v0.2.0

func Localize(docs []*Document, base string)

Localize rewrites document paths the way a caller would type them: forward slashes, and relative to base when the document lives under it.

func MatchDerived

func MatchDerived(value string, spec config.DerivedEdgeSpec) (string, bool)

MatchDerived applies one derived-edge pattern to a field value and returns the captured reference.

func NormalizeHeading added in v0.5.0

func NormalizeHeading(s string) string

NormalizeHeading trims whitespace, trailing colons, and folds case for heading matching.

func Refs

func Refs(fm map[string]any, key string) (refs, invalid []string)

Refs reads a list-valued frontmatter key as raw, un-normalized references. A scalar value is accepted as a single-element list. invalid holds the entries that are not scalars at all, rendered as written: an unquoted wikilink decodes as a nested sequence, and dropping it silently would hide the very link the tool exists to find.

func Scalar added in v0.3.0

func Scalar(value any) (string, bool)

Scalar renders a decoded YAML scalar as the string it was written as, and reports whether the value is a scalar at all. UnmarshalFrontmatter already hands over every written number as its literal text, so the numeric cases are for a frontmatter map assembled in Go rather than read off a document.

func SplitFrontmatter

func SplitFrontmatter(src []byte) (frontmatter, body []byte, ok bool)

SplitFrontmatter separates a leading delimited YAML block from the body. ok is false when the file does not open with a frontmatter delimiter.

func Unmanaged added in v0.5.0

func Unmanaged(dir string, cfg config.Config) []string

Unmanaged returns the paths of Markdown files directly in dir that are not managed documents and are not exempt.

func UnmarshalFrontmatter

func UnmarshalFrontmatter(src []byte) (map[string]any, error)

UnmarshalFrontmatter decodes a frontmatter block with a strict YAML parser. Unknown keys stay allowed: other repositories carry extra frontmatter fields. The parser already rejects duplicate keys, so strictness needs no option.

Every scalar YAML would type as a number comes back as the text it was written as instead. Nothing DocDag reads out of frontmatter is a quantity — an identifier is a name that happens to be spelled in digits — and YAML reads a leading zero as octal, so `supersedes: [0011]` decoded as a number is 9 and the edge lands on document 0009 without a word said. Reading the literal token is what makes an unquoted reference resolve exactly as the quoted one does, and it puts `0x1f` and `0o17`, which used to resolve to some other document too, in front of the invalid_ref check where they belong.

Types

type DerivedEdge

type DerivedEdge struct {
	Spec   config.DerivedEdgeSpec
	Field  string
	Value  string
	Target string
}

DerivedEdge is an edge inferred from a frontmatter field value instead of a declared edge key, such as the MADR status string "superseded by 0003".

func Derived

func Derived(doc *Document, cfg config.Config) []DerivedEdge

Derived applies every configured derived-edge pattern to a document.

type Document

type Document struct {
	Path            string
	Name            string
	ID              model.ID
	Kind            string
	Identity        string
	Frontmatter     map[string]any
	Body            string
	HasFrontmatter  bool
	MatchesPattern  bool
	FrontmatterLine int
	BodyLine        int
	KeyLines        map[string]int
	Err             error
}

Document is one Markdown file after parsing and before graph construction. FrontmatterLine, BodyLine and KeyLines are 1-based file lines, zero when unknown, so a finding can name the exact key or body line it is about.

Kind is the kind whose directory the file was read from, empty on a single-kind corpus. Identity is the token the identifier was read from: the file name under the single-kind rules, and under a kind the frontmatter id where the document writes one and the name's stem where it does not. A finding quotes it when the token yields no identifier at all, which is the one case where a document exists with an empty ID.

func Dir

func Dir(dir string, cfg config.Config) ([]*Document, error)

Dir parses the Markdown files directly in dir whose name matches the preset filename pattern. The name carries the identity, so a file named anything else is not a managed document, whatever its frontmatter says. Non-matching files are not returned as documents.

func Documents added in v0.3.0

func Documents(cfg config.Config) ([]*Document, error)

Documents parses the corpus a configuration describes: every kind's directory, or the single documents directory of a corpus that declares no kinds.

func File

func File(path string, cfg config.Config) (*Document, error)

File parses one Markdown file under the single-kind identity rules: the file name carries the identity. A frontmatter decode failure is recorded on the returned document rather than returned, so later checks still run.

func KindDir added in v0.3.0

func KindDir(dir string, cfg config.Config, kind string) ([]*Document, error)

KindDir parses every Markdown file directly in one kind's directory. Unlike Dir it skips nothing: the directory is what declares a file a document of this kind, so a file that yields no identity is a finding rather than another tool's file.

func KindFile added in v0.3.0

func KindFile(path string, cfg config.Config, kind string) (*Document, error)

KindFile parses one Markdown file as a document of the named kind: the frontmatter id key carries the identity where the document writes one, and the file name's stem otherwise. A file that yields neither is a document without an identity, which CheckDocuments reports rather than skips.

func Kinds added in v0.3.0

func Kinds(cfg config.Config) ([]*Document, error)

Kinds parses every declared kind's directory. The kinds are read in sorted name order and each directory in file-name order, so the corpus is assembled the same way on every run and an identifier collision names the same first document each time.

A directory that is not there is a kind with no documents in it, not a failure. A preset declares the whole vocabulary a corpus may grow into — `preset: spec` names eight directories — and a vault adopts it before it has written its first post-mortem or its first deviation. Refusing to read anything until all eight exist would make the one-line adoption the documentation promises impossible. Every other error still propagates: an unreadable directory is a fact about the machine, not about the corpus.

type FrontmatterError added in v0.2.0

type FrontmatterError struct {
	Message string
	Line    int
	Column  int
}

FrontmatterError is a frontmatter decode failure with the position of the offending token. UnmarshalFrontmatter reports it relative to the first line of the block; File offsets it onto the file.

func (*FrontmatterError) Error added in v0.2.0

func (e *FrontmatterError) Error() string

type Heading added in v0.5.0

type Heading struct {
	Text  string
	Level int
	Line  int
}

Heading is one ATX heading found in a document body. Line is 1-based and relative to the body.

func Headings added in v0.5.0

func Headings(body string) []Heading

Headings extracts ATX headings (# through ######) from a document body, in order of appearance. A heading inside a fenced code block is ignored.

type Link struct {
	Target string
	Alias  string
	Kind   LinkKind
	Line   int
}

Link is one reference-layer link found in a document body. Line is 1-based and relative to the body. Reference links are never validated and never constrain the DAG.

func Links(body string) []Link

Links extracts `[[target]]`, `[[target|alias]]` and relative Markdown links from a document body, in order of appearance. A link written inside a fenced code block or an inline code span is an example, not a reference, and is skipped.

type LinkKind

type LinkKind string

LinkKind distinguishes the reference-layer link syntaxes DocDag recognizes.

const (
	LinkWiki     LinkKind = "wikilink"
	LinkMarkdown LinkKind = "markdown"
)

Recognized reference-layer link kinds.

type RefEntry added in v0.3.0

type RefEntry struct {
	Ref   string
	Attrs map[string]any
}

RefEntry is one entry under an edge key: the raw, un-normalized reference it names and the attributes it was written with. Attrs holds the values as YAML decoded them, so the caller can report a value that is not a scalar rather than lose it; a plain reference carries none.

func RefEntries added in v0.3.0

func RefEntries(fm map[string]any, key string) (entries []RefEntry, invalid []string)

RefEntries reads a list-valued frontmatter key as references that may carry attributes: a scalar item is a plain reference, and a mapping item naming a ref key is an attributed one, the remaining keys being its attributes. As in Refs, invalid holds the entries that are neither, rendered as written — a mapping without a ref names no document, and a caller must not drop it in silence. Only an edge whose spec declares attributes reads its key this way; every other edge keeps taking plain references alone.

Jump to

Keyboard shortcuts

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