- new module kiosk: Manifest, Marshal, Parse, Derive, Generate, Write, Check, StaleError - plugin:manifest [dir] with --check, --pretend, --name, --description - docs: kiosk README, root table row, plugins/marketplace.md, scaffolding row
91 lines
2.9 KiB
Go
91 lines
2.9 KiB
Go
package kiosk
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"sort"
|
|
|
|
"github.com/goccy/go-yaml"
|
|
)
|
|
|
|
// Manifest is one plugin.yaml. Fields are written in declaration order.
|
|
type Manifest struct {
|
|
// Schema is the plugin.yaml format version (SchemaVersion when written).
|
|
Schema int `yaml:"schema"`
|
|
// ID is the plugin ID that plugin.go's ID() returns.
|
|
ID string `yaml:"id"`
|
|
// Module is the go.mod module path: what go get takes.
|
|
Module string `yaml:"module"`
|
|
// Package is the plugin's import path: what summer.yaml lists. It
|
|
// differs from Module for a plugin in a subdirectory of its module.
|
|
Package string `yaml:"package"`
|
|
// Name is the display name: the README's H1 or the name override.
|
|
Name string `yaml:"name"`
|
|
// Description is the README's one-sentence summary or the override.
|
|
Description string `yaml:"description"`
|
|
// Framework is the minimum framework version: the go.mod require of
|
|
// FrameworkModule.
|
|
Framework string `yaml:"framework"`
|
|
// Requires maps each plugin ID that Requires() returns to its minimum
|
|
// version; empty when the plugin ships in the same module or its
|
|
// module is not a go.mod require.
|
|
Requires Requires `yaml:"requires,omitempty"`
|
|
// Overrides holds the --name and --description values; nil when
|
|
// neither is set.
|
|
Overrides *Overrides `yaml:"overrides,omitempty"`
|
|
}
|
|
|
|
// Overrides are the name and description set with summer plugin:manifest
|
|
// --name and --description. They survive regeneration until cleared.
|
|
type Overrides struct {
|
|
Name string `yaml:"name,omitempty"`
|
|
Description string `yaml:"description,omitempty"`
|
|
}
|
|
|
|
// Requires maps a required plugin ID to its minimum version. It marshals
|
|
// with the IDs sorted, so the generated bytes are stable.
|
|
type Requires map[string]string
|
|
|
|
// MarshalYAML emits the map as a sorted mapping.
|
|
func (r Requires) MarshalYAML() (any, error) {
|
|
ids := make([]string, 0, len(r))
|
|
for id := range r {
|
|
ids = append(ids, id)
|
|
}
|
|
sort.Strings(ids)
|
|
out := make(yaml.MapSlice, 0, len(ids))
|
|
for _, id := range ids {
|
|
out = append(out, yaml.MapItem{Key: id, Value: r[id]})
|
|
}
|
|
return out, nil
|
|
}
|
|
|
|
// Marshal returns the plugin.yaml bytes: the Header line, then the fields.
|
|
func Marshal(m Manifest) ([]byte, error) {
|
|
if m.Overrides != nil && *m.Overrides == (Overrides{}) {
|
|
m.Overrides = nil
|
|
}
|
|
body, err := yaml.Marshal(m)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("kiosk: marshal %s: %w", FileName, err)
|
|
}
|
|
var b bytes.Buffer
|
|
b.WriteString(Header)
|
|
b.WriteByte('\n')
|
|
b.Write(body)
|
|
return b.Bytes(), nil
|
|
}
|
|
|
|
// Parse reads plugin.yaml bytes. A schema newer than SchemaVersion is an
|
|
// error that says to update summer; unknown fields are ignored.
|
|
func Parse(data []byte) (Manifest, error) {
|
|
var m Manifest
|
|
if err := yaml.Unmarshal(data, &m); err != nil {
|
|
return Manifest{}, fmt.Errorf("kiosk: parse %s: %w", FileName, err)
|
|
}
|
|
if m.Schema > SchemaVersion {
|
|
return Manifest{}, fmt.Errorf("kiosk: %s has schema %d, this summer reads up to %d; update summer", FileName, m.Schema, SchemaVersion)
|
|
}
|
|
return m, nil
|
|
}
|