package cmd import ( "fmt" "strings" "github.com/runescape-wiki/rsw/internal/extract" "github.com/runescape-wiki/rsw/internal/render" "github.com/runescape-wiki/rsw/internal/wiki" "github.com/spf13/cobra" ) func newPageCmd() *cobra.Command { var pageSection string cmd := &cobra.Command{ Use: "page ", Short: "Fetch and display a wiki page", Long: `Fetches a wiki page and renders it as markdown. Optionally filter to a specific section. Examples: rsw osrs page "Dragon scimitar" rsw rs3 page "Mining" --section "Training"`, Args: cobra.MinimumNArgs(1), RunE: func(cmd *cobra.Command, args []string) error { title := args[0] client := wiki.NewClient(GameBaseURL()) page, err := client.GetPage(title) if err != nil { return fmt.Errorf("failed to fetch page: %w", err) } wikitext := page.Wikitext if pageSection != "" { idx := wiki.FindSectionIndex(page.Sections, pageSection) if idx == -1 { needle := strings.ToLower(pageSection) // Case-insensitive exact match for _, s := range page.Sections { if strings.ToLower(s.Line) == needle { fmt.Sscanf(s.Index, "%d", &idx) break } } // Case-insensitive prefix match (e.g. "Location" → "Locations") if idx == -1 { for _, s := range page.Sections { if strings.HasPrefix(strings.ToLower(s.Line), needle) { fmt.Sscanf(s.Index, "%d", &idx) break } } } // Case-insensitive contains match if idx == -1 { for _, s := range page.Sections { if strings.Contains(strings.ToLower(s.Line), needle) { fmt.Sscanf(s.Index, "%d", &idx) break } } } } if idx == -1 { return fmt.Errorf("section %q not found. Available sections: %s", pageSection, listSections(page.Sections)) } sectionPage, err := client.GetPageSection(title, idx) if err != nil { return fmt.Errorf("failed to fetch section: %w", err) } wikitext = sectionPage.Wikitext } if Raw() { fmt.Println(wikitext) return nil } md := render.New() md.H1(page.Title) if pageSection == "" && len(page.Sections) > 0 { md.H2("Sections") for _, s := range page.Sections { indent := "" if s.Level == "3" { indent = " " } else if s.Level == "4" { indent = " " } md.Line(fmt.Sprintf("%s- %s", indent, s.Line)) } md.Newline() md.HR() } plain := extract.ExtractPlainText(wikitext) md.P(plain) fmt.Print(md.String()) return nil }, } cmd.Flags().StringVar(&pageSection, "section", "", "Fetch only the named section") return cmd } func listSections(sections []wiki.Section) string { names := make([]string, len(sections)) for i, s := range sections { names[i] = s.Line } return strings.Join(names, ", ") } func init() { RegisterCommand(newPageCmd) }