twink/vendor/sourcery.dny.nu/longdistance/processor.go

143 lines
4 KiB
Go
Raw Permalink Normal View History

2025-12-05 12:20:05 +01:00
package longdistance
import (
"log/slog"
"sourcery.dny.nu/longdistance/internal/json"
)
// ProcessorOption can be used to customise the behaviour of a [Processor].
type ProcessorOption func(*Processor)
// Processor represents a JSON-LD processor.
//
// Your application should only ever need one of them. Do not create a new one
// for each request you're handling.
//
// Create one with [NewProcessor] and pass any [ProcessorOption] to configure
// the processor.
type Processor struct {
modeLD10 bool
ordered bool
baseIRI string
compactArrays bool
compactToRelative bool
loader RemoteContextLoaderFunc
logger *slog.Logger
expandContext json.RawMessage
excludeIRIsFromCompaction []string
remapPrefixIRIs map[string]string
}
// NewProcessor creates a new JSON-LD processor.
//
// By default:
// - Processing mode is JSON-LD 1.1. This can handle both JSON-LD 1.0 and
// JSON-LD 1.1 documents. To switch to JSON-LD 1.0 only, configure it with
// [With10Processing].
// - No loader is configured. Without one, remote contexts as well as @import
// contexts cannot be processed. Set it with [WithRemoteContextLoader].
// - Arrays are compacted. Change it with [WithCompactArrays].
// - IRIs can compact to relative IRIs. Change it with
// [WithCompactToRelative].
// - Logger is [slog.DiscardHandler]. Set it with [WithLogger]. The logger is
// only used to emit warnings.
func NewProcessor(options ...ProcessorOption) *Processor {
p := &Processor{
compactArrays: true,
compactToRelative: true,
logger: slog.New(slog.DiscardHandler),
}
for _, opt := range options {
opt(p)
}
return p
}
// With10Processing sets the processing mode to json-ld-1.0.
func With10Processing(b bool) ProcessorOption {
return func(p *Processor) {
p.modeLD10 = b
}
}
// WithRemoteContextLoader sets the context loader function.
func WithRemoteContextLoader(l RemoteContextLoaderFunc) ProcessorOption {
return func(p *Processor) {
p.loader = l
}
}
// WithLogger sets the logger that'll be used to emit warnings during
// processing.
//
// Without a logger no warnings will be emitted when keyword lookalikes are
// encountered that are ignored.
func WithLogger(l *slog.Logger) ProcessorOption {
return func(p *Processor) {
p.logger = l
}
}
// WithOrdered ensures that object elements and language maps are processed in
// lexicographical order.
//
// This is typically not needed, but helps to stabilise the test suite.
func WithOrdered(b bool) ProcessorOption {
return func(p *Processor) {
p.ordered = b
}
}
// WithBaseIRI sets an explicit base IRI to use.
func WithBaseIRI(iri string) ProcessorOption {
return func(p *Processor) {
p.baseIRI = iri
}
}
// WithCompactArrays sets whether single-valued arrays should
// be reduced to their value where possible.
func WithCompactArrays(b bool) ProcessorOption {
return func(p *Processor) {
p.compactArrays = b
}
}
// WithCompactToRelative sets whether IRIs can be transformed into
// relative IRIs during IRI compaction.
func WithCompactToRelative(b bool) ProcessorOption {
return func(p *Processor) {
p.compactToRelative = b
}
}
// WithExpandContext provides an additional out-of-band context
// that's used during expansion.
func WithExpandContext(ctx json.RawMessage) ProcessorOption {
return func(p *Processor) {
p.expandContext = ctx
}
}
// WithExcludeIRIsFromCompaction disables IRI compaction for the specified IRIs.
func WithExcludeIRIsFromCompaction(iri ...string) ProcessorOption {
return func(p *Processor) {
p.excludeIRIsFromCompaction = iri
}
}
// WithRemapPrefixIRIs can remap a prefix IRI during context processing.
//
// Prefixes are only remapped for an exact match.
//
// This is useful to remap the incorrect schema.org# to schema.org/.
func WithRemapPrefixIRIs(old, new string) ProcessorOption {
return func(p *Processor) {
if p.remapPrefixIRIs == nil {
p.remapPrefixIRIs = make(map[string]string, 2)
}
p.remapPrefixIRIs[old] = new
}
}