lint

package
v0.17.0 Latest Latest
Warning

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

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

Documentation

Index

Constants

View Source
const DefaultMaxInputBytes int64 = 2 * 1024 * 1024

DefaultMaxInputBytes is the default file-size cap (2 MB, binary).

Variables

View Source
var KindProcessingInstruction = ast.NewNodeKind("ProcessingInstruction")

KindProcessingInstruction is the ast.NodeKind for ProcessingInstruction.

Functions

func CollectCodeBlockLines

func CollectCodeBlockLines(f *File) map[int]bool

CollectCodeBlockLines walks the AST and returns a set of 1-based line numbers that belong to fenced code blocks (including fence lines) or indented code blocks.

func CollectPIBlockLines added in v0.13.0

func CollectPIBlockLines(f *File) map[int]bool

CollectPIBlockLines walks the AST and returns a set of 1-based line numbers that belong to processing-instruction blocks, including the opening <?... line and the closing ?> line.

func CountLines

func CountLines(b []byte) int

CountLines returns the number of newline-terminated lines in b.

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 NewPIBlockParser added in v0.3.0

func NewPIBlockParser() parser.BlockParser

NewPIBlockParser returns a block parser for processing instructions.

func NewParser added in v0.6.0

func NewParser() parser.Parser

NewParser returns a goldmark parser configured identically to the one used by NewFile. 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.

func ParseFrontMatterFields added in v0.14.0

func ParseFrontMatterFields(fm []byte) (map[string]any, error)

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

func ParseFrontMatterKinds(fm []byte) ([]string, error)

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

func ReadFSFileLimited(fsys fs.FS, name string, max int64) ([]byte, error)

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

func ReadFileLimited(path string, max int64) ([]byte, error)

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

func ResolveFiles(args []string) ([]string, error)

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

func StripFrontMatter(source []byte) (prefix, content []byte)

StripFrontMatter removes YAML front matter delimited by "---\n" from the beginning of source. 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.

The closing fence is recognised only at the start of a line: either as the first bytes after the opening fence (empty FM body) or preceded by a newline. A naive bytes.Index search would otherwise truncate the front matter early when a YAML block-scalar value legitimately contains the literal `---\n` sequence (e.g. a `notes: |` value whose body includes an em-dash row).

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

type ExplanationLeaf struct {
	Path   string
	Value  any
	Source string
}

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.
	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
	// contains filtered or unexported fields
}

File holds a parsed Markdown document and its source.

func NewFile

func NewFile(path string, source []byte) (*File, error)

NewFile parses source as Markdown and returns a File.

func NewFileFromSource

func NewFileFromSource(path string, source []byte, stripFrontMatter bool) (*File, error)

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

func (f *File) ColumnOfOffset(offset int) int

ColumnOfOffset converts a byte offset in Source to a 1-based column number on its line.

func (*File) FullSource

func (f *File) FullSource(body []byte) []byte

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

func (f *File) LineOfOffset(offset int) int

LineOfOffset converts a byte offset in Source to a 1-based line number.

func (*File) SetRootDir added in v0.6.0

func (f *File) SetRootDir(dir string)

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.

func (*GitignoreMatcher) IsIgnored

func (m *GitignoreMatcher) IsIgnored(absPath string, isDir bool) bool

IsIgnored returns true if the given absolute path should be ignored. isDir indicates whether the path is a directory.

type LineRange added in v0.7.0

type LineRange struct {
	From int
	To   int
}

LineRange is an inclusive 1-based line range within a source file.

func (LineRange) Contains added in v0.7.0

func (r LineRange) Contains(l int) bool

Contains reports whether the 1-based line l falls within r.

type ProcessingInstruction added in v0.3.0

type ProcessingInstruction struct {
	ast.BaseBlock
	ClosureLine text.Segment
	Name        string // directive name from <?name
}

ProcessingInstruction is a custom AST block node for processing-instruction blocks (<?name ... ?>). It replaces the default ast.HTMLBlock representation for this PI syntax in CommonMark/HTML.

func (*ProcessingInstruction) Dump added in v0.3.0

func (n *ProcessingInstruction) Dump(source []byte, level int)

Dump implements ast.Node.

func (*ProcessingInstruction) HasClosure added in v0.3.0

func (n *ProcessingInstruction) HasClosure() bool

HasClosure reports whether the PI was closed with ?>. Mirrors ast.HTMLBlock.

func (*ProcessingInstruction) IsRaw added in v0.3.0

func (n *ProcessingInstruction) IsRaw() bool

IsRaw implements ast.Node. Processing instructions contain raw content.

func (*ProcessingInstruction) Kind added in v0.3.0

Kind implements ast.Node.

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 Severity

type Severity string

Severity indicates the severity level of a diagnostic.

const (
	Error   Severity = "error"
	Warning Severity = "warning"
)

Severity levels.

Jump to

Keyboard shortcuts

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