diff --git a/cmd/indexer/main.go b/cmd/indexer/main.go index 4b66838..731bf2c 100644 --- a/cmd/indexer/main.go +++ b/cmd/indexer/main.go @@ -427,11 +427,20 @@ func indexProse(sugar *zap.SugaredLogger, tsClient *typesense.Client, mongoDB *r content = joinParagraphs(strs) } - // Build URL: KB uses /books/kb/{volume}/{slug}, others use /books/{book}/{slug} + // Build URL: KB uses /books/kb/{volume}/{slug}; chapter summaries map + // their "-" slug to the chapter landing page; others use + // /books/{book}/{slug}. var proseURL string - if book == "kb" { + switch { + case book == "kb": proseURL = fmt.Sprintf("/books/kb/%d/%s", volume, slug) - } else { + case docType == "chapter-summary": + if parts := strings.SplitN(slug, "-", 2); len(parts) == 2 { + proseURL = fmt.Sprintf("/books/%s/%s/%s", book, parts[0], parts[1]) + } else { + proseURL = fmt.Sprintf("/books/%s/%s", book, slug) + } + default: proseURL = fmt.Sprintf("/books/%s/%s", book, slug) } diff --git a/cmd/seed-book-intro/main.go b/cmd/seed-book-intro/main.go index a704528..b5a55d9 100644 --- a/cmd/seed-book-intro/main.go +++ b/cmd/seed-book-intro/main.go @@ -35,14 +35,17 @@ type introSegment struct { Type string `json:"type"` Book string `json:"book"` Volume int `json:"volume"` + Chapter int `json:"chapter"` Order int `json:"order"` Paragraphs []string `json:"paragraphs"` } func main() { book := flag.String("book", "", "book code (e.g. bg, cc) — required") - dir := flag.String("dir", "", "directory of intro-segment JSON files "+ - "(default: ../extractor/jsons/books//intro)") + segType := flag.String("type", "intro-segment", + "prose_chapters type to seed (intro-segment | chapter-summary)") + dir := flag.String("dir", "", "directory of segment JSON files "+ + "(default: ../extractor/jsons/books//)") flag.Parse() if *book == "" { @@ -51,7 +54,11 @@ func main() { } segDir := *dir if segDir == "" { - segDir = filepath.Join("..", "extractor", "jsons", "books", *book, "intro") + sub := "intro" + if *segType == "chapter-summary" { + sub = "chapter-summaries" + } + segDir = filepath.Join("..", "extractor", "jsons", "books", *book, sub) } cfg, err := config.Load() @@ -93,7 +100,7 @@ func main() { if err := json.Unmarshal(raw, &seg); err != nil { sugar.Fatalf("parse %s: %v", name, err) } - if seg.Book != *book || seg.Type != "intro-segment" { + if seg.Book != *book || seg.Type != *segType { sugar.Warnf("skipping %s (book=%q type=%q)", name, seg.Book, seg.Type) continue } @@ -101,7 +108,7 @@ func main() { } if len(segments) == 0 { - sugar.Fatalf("no %s intro-segments found in %s", *book, segDir) + sugar.Fatalf("no %s %s docs found in %s", *book, *segType, segDir) } ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) @@ -111,22 +118,26 @@ func main() { del, err := col.DeleteMany(ctx, map[string]any{ "book": *book, - "type": "intro-segment", + "type": *segType, }) if err != nil { - sugar.Fatalf("delete existing %s intro-segments: %v", *book, err) + sugar.Fatalf("delete existing %s %s docs: %v", *book, *segType, err) } - sugar.Infof("removed %d existing %s intro-segment(s)", del.DeletedCount, *book) + sugar.Infof("removed %d existing %s %s doc(s)", del.DeletedCount, *book, *segType) docs := make([]any, 0, len(segments)) for _, seg := range segments { - // chapter is null for intro-segments (matches the ProseChapterDoc shape). + // chapter is null unless the segment carries one (chapter-summaries do). + var chapter any + if seg.Chapter > 0 { + chapter = seg.Chapter + } docs = append(docs, map[string]any{ "book": *book, "volume": 0, - "chapter": nil, + "chapter": chapter, "title": seg.Title, - "type": "intro-segment", + "type": *segType, "slug": seg.Slug, "order": seg.Order, "paragraphs": seg.Paragraphs, @@ -136,7 +147,7 @@ func main() { res, err := col.InsertMany(ctx, docs) if err != nil { - sugar.Fatalf("insert %s intro-segments: %v", *book, err) + sugar.Fatalf("insert %s %s docs: %v", *book, *segType, err) } - sugar.Infof("inserted %d %s intro-segment(s)", len(res.InsertedIDs), *book) + sugar.Infof("inserted %d %s %s doc(s)", len(res.InsertedIDs), *book, *segType) }