package cmd import ( "fmt" "strings" "github.com/runescape-wiki/rsw/internal/htmlconv" "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 var complete bool cmd := &cobra.Command{ Use: "page ", Short: "Fetch and display a wiki page", Long: `Fetches a wiki page and renders its table of contents by default. Use --section to get a specific section, or --complete for the full page. Examples: rsw osrs page "Dragon scimitar" rsw osrs page "Dragon scimitar" --section "Combat styles" rsw osrs page "Mining" --complete 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()) if Raw() { page, err := client.GetPage(title) if err != nil { return fmt.Errorf("failed to fetch page: %w", err) } fmt.Println(page.Wikitext) return nil } page, err := client.GetPageHTML(title) if err != nil { return fmt.Errorf("failed to fetch page: %w", err) } if pageSection != "" { body := htmlconv.ExtractSection(page.HTML, pageSection) if body == "" { sections := htmlconv.ListSections(page.HTML) return fmt.Errorf("section %q not found. Available sections: %s", pageSection, formatSectionNames(sections)) } md := render.New() md.H1(page.Title) md.Line(body) fmt.Print(md.String()) return nil } md := render.New() md.H1(page.Title) sections := htmlconv.ListSections(page.HTML) if len(sections) > 0 { md.H2("Sections") for _, s := range sections { indent := "" if s.Level == 3 { indent = " " } else if s.Level >= 4 { indent = " " } md.Line(fmt.Sprintf("%s- %s", indent, s.Name)) } md.Newline() md.HR() } if complete { md.Line(htmlconv.Convert(page.HTML)) } else { md.Line("Use --section <name> to fetch a specific section, or --complete for the full page.") } fmt.Print(md.String()) return nil }, } cmd.Flags().StringVar(&pageSection, "section", "", "Fetch only the named section") cmd.Flags().BoolVar(&complete, "complete", false, "Fetch the complete page content (default shows TOC only)") return cmd } func formatSectionNames(sections []htmlconv.SectionInfo) string { names := make([]string, len(sections)) for i, s := range sections { names[i] = s.Name } return strings.Join(names, ", ") } func init() { RegisterCommand(newPageCmd) }