- комментарии, тексты ошибок, вывод CLI и сообщения тестов теперь на английском - по-русски остались только литералы словаря ru и содержимое фикстур: это данные под проверкой, а не текст инструмента - согласование числительных в итоге упростилось до английского plural
84 lines
2.2 KiB
Go
84 lines
2.2 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
|
|
|
|
// 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
|
|
default:
|
|
front.Unknown = append(front.Unknown, key)
|
|
}
|
|
}
|
|
return front, len(lines) + 1, fmt.Errorf("front matter is not closed by a --- delimiter")
|
|
}
|