feat: graph validation and custom JSON-LD
- seo_schema (seoschema, E8) with the C17 server rules: invalid JSON with line and column, non-objects, 16 KB, depth 8, a literal <script and a type outside the kind's list refused; the value re-serialised - a custom node with a generated @id merges into it (schema.merged save notice), other nodes are appended to the graph - seo_primary_parent (seoparent) for article types; both values stored in the entry data on every locale row - the seo_graph widget action (E9 data), P1 primary_gone and the P2 schema type and breadcrumb trail rows - GET /_seo/api/v1/graph and MCP seo_get_graph; seo_set_url_seo and apply_batch accept primary_parent and schema The graph tool lands with the validation: the operations parity test binds the seo_graph widget action to its tool.
This commit is contained in:
@@ -160,3 +160,39 @@ func (s *Service) Trail(ctx context.Context, db *gorm.DB, settings models.Settin
|
||||
}
|
||||
return append(out, schema.Crumb{Name: name, URL: site + path, Path: path})
|
||||
}
|
||||
|
||||
// ParentOption is one choice of the primary category field (P33-23).
|
||||
type ParentOption struct {
|
||||
Value string `json:"value"`
|
||||
Label string `json:"label"`
|
||||
}
|
||||
|
||||
// ParentOptions lists a record's parents as primary category choices, in
|
||||
// descriptor order, labelled with their title in locale (the default
|
||||
// locale when "").
|
||||
func (s *Service) ParentOptions(ctx context.Context, key, id, locale string) []ParentOption {
|
||||
out := []ParentOption{}
|
||||
reg := s.Registry()
|
||||
if reg == nil || key == "" || id == "" {
|
||||
return out
|
||||
}
|
||||
rec, err := reg.Describe(ctx, key, id, s.UnprefixedLocale())
|
||||
if err != nil || rec == nil {
|
||||
return out
|
||||
}
|
||||
if locale == "" {
|
||||
if db, err := s.DB(ctx); err == nil {
|
||||
locale = s.DefaultLocale(ctx, db)
|
||||
}
|
||||
}
|
||||
for _, ref := range rec.Parents {
|
||||
label := ParentValue(ref)
|
||||
if parent, err := reg.Describe(ctx, ref.Type, ref.ID, s.UnprefixedLocale()); err == nil && parent != nil {
|
||||
if l := contentLocale(parent, locale); strings.TrimSpace(l.Title) != "" {
|
||||
label = l.Title
|
||||
}
|
||||
}
|
||||
out = append(out, ParentOption{Value: ParentValue(ref), Label: label})
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user