Documentation
¶
Index ¶
- Constants
- Variables
- func CollectCodeBlockLines(f *File) map[int]bool
- func CollectPIBlockLines(f *File) map[int]bool
- func CountLines(b []byte) int
- func FindFencedOpenLine(f *File, fcb *ast.FencedCodeBlock) int
- func NewParser() parser.Parser
- func PIBlockParserPrioritized() util.PrioritizedValue
- func ParseFrontMatterFields(fm []byte) (map[string]any, error)
- func ParseFrontMatterKinds(fm []byte) ([]string, error)
- func ReadFSFileLimited(fsys fs.FS, name string, max int64) ([]byte, error)
- func ReadFileLimited(path string, max int64) ([]byte, error)
- func ResolveFiles(args []string) ([]string, error)
- func ResolveFilesWithOpts(args []string, opts ResolveOpts) ([]string, error)
- func StripFrontMatter(source []byte) (prefix, content []byte)
- type Diagnostic
- type Explanation
- type ExplanationLeaf
- type File
- func (f *File) AdjustDiagnostics(diags []Diagnostic)
- func (f *File) ColumnOfOffset(offset int) int
- func (f *File) FullSource(body []byte) []byte
- func (f *File) GetGitignore() *GitignoreMatcher
- func (f *File) LineOfOffset(offset int) int
- func (f *File) LinkReferences() []Reference
- func (f *File) Memo(key string, build func() any) any
- func (f *File) MemoFile(key string, build func(*File) any) any
- func (f *File) SetRootDir(dir string)
- type GitignoreMatcher
- type LineRange
- type ProcessingInstruction
- type Reference
- type ResolveOpts
- type RunCache
- type Severity
Constants ¶
const DefaultMaxInputBytes int64 = 2 * 1024 * 1024
DefaultMaxInputBytes is the default file-size cap (2 MB, binary).
Variables ¶
var KindProcessingInstruction = markdown.KindProcessingInstruction
KindProcessingInstruction is the ast.NodeKind for ProcessingInstruction, re-exported from pkg/markdown so there is a single registered kind value in the tree.
Functions ¶
func CollectCodeBlockLines ¶
CollectCodeBlockLines returns a set of 1-based line numbers that belong to fenced code blocks (including fence lines) or indented code blocks. The walk is computed once per File and cached; the returned map is shared read-only and must not be mutated.
func CollectPIBlockLines ¶ added in v0.13.0
CollectPIBlockLines returns a set of 1-based line numbers that belong to processing-instruction blocks, including the opening <?... line and the closing ?> line. The walk is computed once per File and cached; the returned map is shared read-only and must not be mutated.
func CountLines ¶
CountLines returns the number of newline-terminated lines in b, forwarded from pkg/markdown.
func FindFencedOpenLine ¶ added in v0.16.0
func FindFencedOpenLine(f *File, fcb *ast.FencedCodeBlock) int
FindFencedOpenLine returns the 1-based line number of the opening fence. Returns 0 when the block has neither an info string nor any content lines — the truly-empty fenced shape that goldmark exposes no source position for. Callers must NOT clamp 0 to 1 for section- range filtering or diagnostic anchoring: clamping would mis-locate the block at the top of the document and silently move any diagnostic to a line that has nothing to do with the source. The preferred fallback is sibling-derived inference — see internal/schema.topLevelBlocks for an implementation that walks adjacent blocks to recover a sensible position.
func NewParser ¶ added in v0.6.0
NewParser returns mdsmith's canonical goldmark parser, forwarded from pkg/markdown. Rules that need to re-inspect a document (for example, to consult the link reference definition map) should use this so that processing-instruction blocks and other mdsmith-specific parsing decisions stay consistent with the original lint parse.
func PIBlockParserPrioritized ¶ added in v0.3.0
func PIBlockParserPrioritized() util.PrioritizedValue
PIBlockParserPrioritized returns the PI parser with its priority for registration, forwarded from pkg/markdown. Kept because internal/schema registers it directly; the parser logic itself lives in pkg/markdown.
func ParseFrontMatterFields ¶ added in v0.14.0
ParseFrontMatterFields decodes a YAML front-matter block (including its --- delimiters) into a map of top-level keys to raw values. Returns (nil, nil) when fm is empty, whitespace-only, or decodes to YAML null. Returns an error when the payload is a non-null scalar or a sequence — both reject because the field-presence selector requires named keys — or when the YAML is otherwise invalid. Used by the kind-assignment field-presence selector; a field is considered present when its value is non-null.
func ParseFrontMatterKinds ¶ added in v0.7.0
ParseFrontMatterKinds extracts the kinds: list from a YAML front-matter block (including its --- delimiters). Returns nil kinds and nil error if the block is nil or the kinds key is absent. Returns an error if the YAML contains anchors/aliases or cannot be parsed.
func ReadFSFileLimited ¶ added in v0.6.0
ReadFSFileLimited reads name from fsys, returning an error if the file exceeds max bytes. When max <= 0 or max == math.MaxInt64 no limit is applied (unlimited mode).
func ReadFileLimited ¶ added in v0.6.0
ReadFileLimited reads path from disk, returning an error if the file exceeds max bytes. When max <= 0 or max == math.MaxInt64 no limit is applied (unlimited mode). MaxInt64 is treated as unlimited because the +1 sentinel used internally would overflow.
func ResolveFiles ¶
ResolveFiles takes positional arguments and returns deduplicated, sorted markdown file paths. It supports individual files, directories (recursive *.md and *.markdown), and glob patterns. Returns an error for nonexistent paths (that are not glob patterns). By default, directory walking respects .gitignore files.
func ResolveFilesWithOpts ¶
func ResolveFilesWithOpts(args []string, opts ResolveOpts) ([]string, error)
ResolveFilesWithOpts is like ResolveFiles but accepts options to control behavior such as gitignore filtering.
func StripFrontMatter ¶
StripFrontMatter removes YAML front matter delimited by "---\n" from the beginning of source, forwarding to pkg/markdown so the front-matter split lives in one place. It returns the front matter block (including delimiters) and the remaining content; if no front matter is found, prefix is nil and content equals source.
Types ¶
type Diagnostic ¶
type Diagnostic struct {
File string
Line int
Column int
RuleID string
RuleName string
Severity Severity
Message string
SourceLines []string // context lines around the diagnostic; empty if unavailable
SourceStartLine int // 1-based line number of first entry in SourceLines
// Explanation, when non-nil, attaches per-leaf provenance for the
// rule that fired. Populated by the CLI when --explain is on.
Explanation *Explanation
}
Diagnostic represents a single lint finding.
type Explanation ¶ added in v0.7.1
type Explanation struct {
Rule string
Leaves []ExplanationLeaf
}
Explanation describes the provenance of a rule's effective config at the file that produced a diagnostic. It is attached to a Diagnostic when the CLI runs with --explain so the trailer / JSON output can name the rule and the source of each setting that contributed.
type ExplanationLeaf ¶ added in v0.7.1
ExplanationLeaf is one leaf setting and the layer that set its final value, formatted for surface output.
type File ¶
type File struct {
Path string
Source []byte
Lines [][]byte
AST ast.Node
FS fs.FS
RootFS fs.FS
RootDir string
FrontMatter []byte
LineOffset int
// StripFrontMatter records whether this file was parsed in
// front-matter-stripping mode. Rules that read other files
// from the corpus should mirror the same mode so that line
// numbers in cross-file diagnostics are computed against the
// same coordinate system as the current file.
StripFrontMatter bool
// MaxInputBytes is the maximum file size in bytes that rules
// should enforce when reading secondary files (includes, schemas,
// cross-references). Zero or negative means unlimited.
MaxInputBytes int64
// GitignoreFunc is a lazy factory for the gitignore matcher.
// It is called at most once (on first access via GetGitignore)
// and the result is cached. Rules that do not call GetGitignore
// never trigger matcher construction. sync.Once keeps the lazy
// build race-free if a *File is shared across goroutines.
GitignoreFunc func() *GitignoreMatcher
// GeneratedRanges records the content line ranges of generated
// sections (<?include?> / <?catalog?> bodies). Diagnostics whose
// line falls within these ranges are suppressed when linting the
// host file — the source file is responsible for those bytes.
GeneratedRanges []LineRange
// RunCache is the engine-owned read cache shared by every File
// processed in one engine.Run pass. Catalog and include rules
// consult it before falling back to per-Check Memo so a target
// globbed by N host-file catalogs is read once per run, not N
// times. nil for struct-literal Files in unit tests; the
// catalog rule then takes the per-Check fallback path.
RunCache *RunCache
// contains filtered or unexported fields
}
File holds a parsed Markdown document and its source.
func NewFile ¶
NewFile parses source as Markdown and returns a File. The parse itself is delegated to pkg/markdown's pooled canonical parser, so a single goldmark configuration backs every parse path.
func NewFileFromSource ¶
NewFileFromSource creates a File from raw source bytes. When stripFrontMatter is true it strips YAML front matter, stores the prefix in FrontMatter, computes LineOffset via CountLines, and parses only the stripped content.
func (*File) AdjustDiagnostics ¶
func (f *File) AdjustDiagnostics(diags []Diagnostic)
AdjustDiagnostics adds the file's LineOffset to each diagnostic's Line.
func (*File) ColumnOfOffset ¶ added in v0.8.0
ColumnOfOffset converts a byte offset in Source to a 1-based column number on its line.
func (*File) FullSource ¶
FullSource prepends the stored FrontMatter to body. It allocates a new slice to avoid mutating FrontMatter's backing array.
func (*File) GetGitignore ¶ added in v0.5.0
func (f *File) GetGitignore() *GitignoreMatcher
GetGitignore returns the gitignore matcher for this file, creating it lazily on first call. Returns nil if no GitignoreFunc was configured.
func (*File) LineOfOffset ¶
LineOfOffset converts a byte offset in Source to a 1-based line number. The line is 1 plus the number of newlines that occur strictly before offset (a newline exactly at offset starts the next line, so it does not count) — identical to a linear scan, but O(log n) via binary search over the cached newline index.
func (*File) LinkReferences ¶ added in v0.20.0
LinkReferences returns the link reference definitions goldmark found in this document. It is computed once and cached. On the normal path it reads the context from the parse NewFile already performed (no extra parse); a File built as a struct literal has no such context, so the first call parses Source once. The returned slice is shared read-only.
func (*File) Memo ¶ added in v0.23.0
Memo returns the value for key, computing it once via build on the first request within this File's lifetime and serving the cached value thereafter. It exists so a rule whose passes would otherwise recompute the same expensive per-Check derivation can share one result: the catalog directive's resolved entries, for example, are otherwise rebuilt by the generate, injection, and case-mismatch passes — three globs and front-matter reads of every matched file per directive. The File is discarded after each Check, so nothing is cached across files or runs.
build is invoked directly (no wrapping closure) so the call adds no per-Memo-call allocation beyond the cold-path memoEntry itself.
Panic safety mirrors sync.Once: if build panics, the entry is still marked done (via the deferred Store) and the mutex is released (via the deferred Unlock), so the panic propagates without leaving the per-File memo in a deadlocked state. Subsequent calls on the same key serve the zero-value cached result instead of re-running build, matching upstream sync.Once.
func (*File) MemoFile ¶ added in v0.23.0
MemoFile is the *File-passing variant of Memo: build receives this File as an argument instead of capturing it in a closure. Callers whose build needs nothing beyond File data can pass a package- level function value, which avoids the per-call closure allocation the plain `Memo` form forces on every invocation. The hot astutil.CollectSectionParagraphs path is the canonical user.
Panic safety matches Memo's contract: defer Unlock + defer done.Store(true) keep the per-entry mutex from leaking a lock and match sync.Once's "panic still marks done" semantics.
func (*File) SetRootDir ¶ added in v0.6.0
SetRootDir configures the project root directory and its fs.FS together.
type GitignoreMatcher ¶
type GitignoreMatcher struct {
// contains filtered or unexported fields
}
GitignoreMatcher checks whether a given path is ignored according to .gitignore rules. It supports multiple .gitignore files at different directory levels, including negation patterns.
func NewGitignoreMatcher ¶
func NewGitignoreMatcher(root string) *GitignoreMatcher
NewGitignoreMatcher creates a matcher by collecting .gitignore files from the given root directory and all its subdirectories. It also looks for .gitignore files in ancestor directories up to the filesystem root.
type ProcessingInstruction ¶ added in v0.3.0
type ProcessingInstruction = markdown.ProcessingInstruction
ProcessingInstruction is the custom AST block node for <?name ... ?> blocks. It is an alias for the canonical type in pkg/markdown so the linter's many callers (type switches in schema, index, export, rename, gensection, …) keep working without importing the public package directly while the node definition lives in exactly one place.
type Reference ¶ added in v0.20.0
Reference is a link reference definition discovered during the parse, re-exported from goldmark so callers of LinkReferences need not import the parser package.
type ResolveOpts ¶
type ResolveOpts struct {
// UseGitignore enables filtering of walked directories by .gitignore
// rules. When true (the default), files matched by .gitignore patterns
// are skipped during directory walking. Explicitly named file paths are
// never filtered by gitignore. Defaults to true when the zero value is
// used (see DefaultResolveOpts).
UseGitignore *bool
// FollowSymlinks opts in to following symbolic links that
// resolve to regular files. The zero value skips all symlinks,
// which is the secure default.
//
// Symlinks that resolve to anything other than a regular file
// are always skipped, regardless of this flag: directories
// (filepath.Walk is Lstat-based and does not descend a symlink
// root) as well as FIFOs, devices, and sockets (reading them
// during linting could block or fail unexpectedly).
FollowSymlinks bool
}
ResolveOpts controls how file resolution behaves.
func DefaultResolveOpts ¶
func DefaultResolveOpts() ResolveOpts
DefaultResolveOpts returns options with defaults applied.
type RunCache ¶ added in v0.23.0
type RunCache struct {
// contains filtered or unexported fields
}
RunCache memoizes per-target-file reads (front matter, include adjacency) across every host file processed in one engine.Run pass. Cache keys are absolute filesystem paths, so two host files whose catalogs match the same target share a single read of that target — closing the cross-host redundancy the per-File Memo could not.
The cache is safe for concurrent readers (the parallel file worker pool and the LSP's concurrent request goroutines).
A one-shot mdsmith check sees an immutable corpus, so the cache is trivially safe there. The LSP keeps one RunCache for the server lifetime and calls Invalidate when a document edit could change what the next Check would read from disk.
func NewRunCache ¶ added in v0.23.0
func NewRunCache() *RunCache
NewRunCache returns an empty cache ready to be installed on engine.Runner.RunCache.
func (*RunCache) FrontMatter ¶ added in v0.23.0
FrontMatter returns build's result for absPath, computed at most once per absPath in this cache's lifetime. Concurrent callers with the same key block on the same once and observe the same value.
func (*RunCache) Includes ¶ added in v0.23.0
Includes returns build's result for absPath. The value is the list of absolute filesystem paths every <?include?> in the file at absPath resolves to. Position-independent so two host files whose f.FS roots differ can still share the cached adjacency.
func (*RunCache) Invalidate ¶ added in v0.23.0
Invalidate drops the front-matter and include entries for absPath. The LSP calls this from didChange / didSave / didChangeWatchedFiles so the next Check that crosses absPath re-reads from disk.