Files
convy/internal/doc/front.go
T
av ccf046fb7b suite check: реализована проверка целостности набора
- разбор документа по языку конвенций: шапка, области правил, блоки под метками
- проверки формы правила, распространения, ссылок и самого suite.toml
- словарь языка живёт в бинаре реестром «версия × естественный язык», темы и
  префиксы берутся только из манифеста
2026-07-27 09:53:07 +03:00

81 lines
2.5 KiB
Go

package doc
import (
"fmt"
"strings"
)
// Front — шапка файла. Ключей немного и все они плоские, поэтому разбор здесь
// свой: тащить YAML ради четырёх строк `ключ: значение` не за что.
//
// Ось слоя объявляется здесь ключами lang и stack, а не выводится из пути
// (META-38); отсутствие обоих означает базовый слой темы.
type Front struct {
Topic string
Prefix string
Lang string
Stack string
Extends string
// At — номер строки, на которой объявлен ключ; нужен, чтобы находка
// показывала на объявление, а не на начало файла.
At map[string]int
// Unknown — ключи, которых модель не знает.
Unknown []string
// End — номер строки закрывающего разделителя. Тело файла начинается
// со следующей.
End int
// Present — была ли шапка вообще.
Present bool
}
// Axis отвечает, объявлена ли у слоя ось. Слой без ключей оси — базовый.
func (f Front) Axis() bool {
return f.Lang != "" || f.Stack != ""
}
// parseFront разбирает шапку из строк файла. Возвращает шапку и номер первой
// строки тела.
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("строка %d шапки не имеет вида «ключ: значение»", 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("шапка не закрыта разделителем ---")
}