Help us shape the future of Go! Take the 2026 Go Developer Survey

citation

package module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Sep 20, 2026 License: MIT Imports: 14 Imported by: 0

README

citation

A Go library for parsing CITATION.cff files and validating citation metadata, with no third-party dependencies. Reads bytes, readers, or files and preserves source positions, unknown fields, and numeric spelling.

Installation

go get github.com/git-pkgs/citation

Usage

package main

import (
	"fmt"
	"log"

	"github.com/git-pkgs/citation"
)

func main() {
	doc, err := citation.ReadFile("CITATION.cff", citation.ParseOptions{})
	if err != nil {
		log.Fatal(err)
	}

	fmt.Printf("Title: %s\n", doc.Title())
	fmt.Printf("CFF version: %s\n", doc.CFFVersion())
	for _, author := range doc.Authors() {
		if author.IsEntity() {
			fmt.Println(author.Name())
		} else {
			fmt.Println(author.GivenNames(), author.FamilyNames())
		}
	}
	for _, issue := range doc.Validate() {
		fmt.Println(issue.Path, issue.Code, issue.Message)
	}
}

Use Parse(data) for bytes from a Git blob or another source, ParseWithOptions(data, opts) to set limits, or Read(reader, opts) for an io.Reader. Read leaves the reader open. Repository discovery, blob caching, and concurrency limits remain with the caller.

Documents are immutable and can be read concurrently. Parsing copies retained text, so callers may reuse input buffers after a call returns. Collection accessors return copies of their slices.

Metadata

Authors, Contact, References, and PreferredCitation provide typed views of common fields. Use Get to access any field, including unknown fields and invalid metadata:

fmt.Println(doc.Get("doi").Text())
for _, keyword := range doc.Get("keywords").Items() {
	fmt.Println(keyword.Text())
}

Values expose Kind, Text, Items, Fields, and Position. A missing field has kind Missing, distinct from an explicit YAML Null.

Errors

The library returns errors without logging or terminating the process. Use errors.Is with ErrSyntax, ErrType, ErrUnsupported, ErrLimit, or ErrOptions to distinguish failures. errors.As exposes a *citation.Error with a diagnostic, and file and reader errors retain their underlying causes.

Compatibility

Parsing and validation are separate. Validate checks CFF 1.2.0 against rules generated from the checked-in official schema. Other versions produce an unsupported_version diagnostic; parsing preserves their declared version and metadata. A successful parse alone does not establish CFF validity.

The parser supports UTF-8 YAML block and flow collections, multiline scalars, standard scalar escapes, core tags, anchors, and aliases. Duplicate keys, multiple documents, cycles, and unresolved aliases are errors. Merge keys, custom tags, and non-UTF-8 encodings are unsupported. Full YAML conformance has not been established. Historical schema validation, editing, YAML output, and citation formatting are not implemented yet.

Limits

Default limits are 1 MiB of input, depth 64, 100,000 nodes including alias expansion, 4 MiB of scalar content, 4,096 bytes per numeric scalar, and 100 validation diagnostics. ParseOptions allows larger finite limits; zero selects the defaults and negative limits are errors. Validation adds a diagnostic_limit entry when further problems are omitted. A blocked reader requires a deadline supplied by its caller.

Testing

go test ./...
go test -race ./...
go test -fuzz=FuzzParse -fuzztime=30s

Tests use checked-in fixtures and run offline. go generate ./... regenerates validation rules from the checked-in schema and rejects unknown schema keywords.

Run the example with go run ./examples/read path/to/CITATION.cff, or supply - to read a Git blob through standard input.

License

MIT

Documentation

Overview

Package citation reads Citation File Format metadata without external dependencies.

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrSyntax      = errors.New("invalid YAML")
	ErrType        = errors.New("invalid value type")
	ErrUnsupported = errors.New("unsupported YAML")
	ErrLimit       = errors.New("resource limit exceeded")
	ErrOptions     = errors.New("invalid parse options")
)

Functions

This section is empty.

Types

type Actor

type Actor struct {
	// contains filtered or unexported fields
}

func (Actor) FamilyNames

func (a Actor) FamilyNames() string

func (Actor) Get

func (a Actor) Get(name string) Value

func (Actor) GivenNames

func (a Actor) GivenNames() string

func (Actor) IsEntity

func (a Actor) IsEntity() bool

func (Actor) Name

func (a Actor) Name() string

type Diagnostic

type Diagnostic struct {
	Code    string `json:"code"`
	Path    string `json:"path,omitempty"`
	Message string `json:"message"`
	Position
}

Diagnostic describes a problem without requiring consumers to parse its message.

type Document

type Document struct {
	// contains filtered or unexported fields
}

Document owns the parsed metadata, including unknown and invalid fields.

func Parse

func Parse(data []byte) (*Document, error)

func ParseWithOptions

func ParseWithOptions(data []byte, opts ParseOptions) (*Document, error)

func Read

func Read(r io.Reader, opts ParseOptions) (*Document, error)

func ReadFile

func ReadFile(path string, opts ParseOptions) (*Document, error)

func (*Document) Authors

func (d *Document) Authors() []Actor

func (*Document) CFFVersion

func (d *Document) CFFVersion() string

func (*Document) Contact

func (d *Document) Contact() []Actor

func (*Document) Fields

func (d *Document) Fields() []Field

func (*Document) Get

func (d *Document) Get(name string) Value

func (*Document) PreferredCitation

func (d *Document) PreferredCitation() (Reference, bool)

func (*Document) References

func (d *Document) References() []Reference

func (*Document) Title

func (d *Document) Title() string

func (*Document) Validate

func (d *Document) Validate() []Diagnostic

Validate checks the declared schema without modifying metadata. Unsupported versions receive a diagnostic rather than current-version rules.

func (*Document) Version

func (d *Document) Version() Value

type Error

type Error struct {
	Diagnostic
	Cause error
}

Error wraps a parse failure and its category for errors.Is and errors.As.

func (*Error) Error

func (e *Error) Error() string

func (*Error) Unwrap

func (e *Error) Unwrap() error

type Field

type Field struct {
	Name     string
	Value    Value
	Position Position
}

type Kind

type Kind uint8

Kind distinguishes YAML scalar types and collections. A zero Value is missing.

const (
	Missing Kind = iota
	Null
	String
	Number
	Boolean
	Sequence
	Mapping
)

type ParseOptions

type ParseOptions struct {
	MaxBytes       int64
	MaxDepth       int
	MaxNodes       int
	MaxScalarBytes int
	MaxNumberBytes int
	MaxDiagnostics int
}

ParseOptions bounds work for untrusted inputs. Zero fields select defaults.

type Position

type Position struct {
	Line   int `json:"line,omitempty"`
	Column int `json:"column,omitempty"`
}

Position identifies a one-based source line and column. Zero means unavailable.

type Reference

type Reference struct {
	// contains filtered or unexported fields
}

func (Reference) Authors

func (r Reference) Authors() []Actor

func (Reference) Get

func (r Reference) Get(name string) Value

func (Reference) Title

func (r Reference) Title() string

func (Reference) Type

func (r Reference) Type() string

type Value

type Value struct {
	// contains filtered or unexported fields
}

Value retains scalar spelling, collection order, and source position. Its contents are immutable; accessors return copies of collection slices.

func (Value) Fields

func (v Value) Fields() []Field

func (Value) Get

func (v Value) Get(name string) Value

func (Value) Items

func (v Value) Items() []Value

func (Value) Kind

func (v Value) Kind() Kind

func (Value) Position

func (v Value) Position() Position

func (Value) Text

func (v Value) Text() string

Directories

Path Synopsis
examples
read command
Command read demonstrates parsing a file or a Git blob supplied on standard input.
Command read demonstrates parsing a file or a Git blob supplied on standard input.
internal
generate command
Command generate compiles the pinned CFF schema into Go validation rules.
Command generate compiles the pinned CFF schema into Go validation rules.

Jump to

Keyboard shortcuts

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