Files
convy/internal/doc/front.go
T
av 23d88c4048 проектные команды и ссылки на источник
- заведён internal/source: уровни ссылаются друг на друга путём на диске
  или git-репозиторием, ревизия закрепляется хвостом #ref; клон делается
  заново и удаляется, кэша нет
- добавлены init, add, pull, list, check в проекте — манифест
  .conventions.toml, сборка копий по разу на компонент, маркер локальной
  части, READING.md рядом
- проверки формы развязаны с набором: принимают lang.Vocabulary, а язык
  копии узнаётся по строке о версии — манифеста рядом с ней нет
2026-07-27 20:42:18 +03:00

91 lines
2.5 KiB
Go

package doc
import (
"fmt"
"strings"
)
// Front is the front matter of a file. There are few keys and all of them are
// flat, so the parsing is done here: pulling in YAML for four `key: value`
// lines earns nothing.
//
// The axis of a layer is declared here by the lang and stack keys rather than
// derived from the path (META-38); the absence of both means the base layer of
// the topic.
type Front struct {
Topic string
Prefix string
Lang string
Stack string
Extends string
// Origin is the key a copy carries in a consuming repository: the name of
// the topic it was assembled from. It is the whole front matter of a copy
// and it appears nowhere in a suite — a file that lost it is no longer a
// copy and is never overwritten again.
Origin string
// At is the line a key was declared on, so a finding can point at the
// declaration rather than at the top of the file.
At map[string]int
// Unknown lists keys the model does not know.
Unknown []string
// End is the line of the closing delimiter. The body of the file starts
// on the next one.
End int
// Present says whether there was any front matter at all.
Present bool
}
// Axis reports whether the layer declares an axis. A layer without one is the
// base layer.
func (f Front) Axis() bool {
return f.Lang != "" || f.Stack != ""
}
// parseFront parses the front matter out of the file's lines. It returns the
// front matter and the number of the first line of the body.
func parseFront(lines []string) (Front, int, error) {
front := Front{At: make(map[string]int)}
if len(lines) == 0 || strings.TrimSpace(lines[0]) != "---" {
return front, 1, nil
}
front.Present = true
for i := 1; i < len(lines); i++ {
line := lines[i]
num := i + 1
if strings.TrimSpace(line) == "---" {
front.End = num
return front, num + 1, nil
}
if strings.TrimSpace(line) == "" {
continue
}
key, value, ok := strings.Cut(line, ":")
if !ok {
return front, num, fmt.Errorf("front matter line %d is not of the form \"key: value\"", num)
}
key = strings.TrimSpace(key)
value = strings.TrimSpace(value)
front.At[key] = num
switch key {
case "topic":
front.Topic = value
case "prefix":
front.Prefix = value
case "lang":
front.Lang = value
case "stack":
front.Stack = value
case "extends":
front.Extends = value
case "origin":
front.Origin = value
default:
front.Unknown = append(front.Unknown, key)
}
}
return front, len(lines) + 1, fmt.Errorf("front matter is not closed by a --- delimiter")
}