article.go (1995B)
1 package article 2 3 import ( 4 "fmt" 5 "os/exec" 6 "strings" 7 "time" 8 9 "git.figbert.com/caret/ui" 10 "git.figbert.com/caret/utils" 11 12 "github.com/charmbracelet/bubbletea" 13 "github.com/charmbracelet/glamour" 14 gloss "github.com/charmbracelet/lipgloss" 15 16 md "github.com/JohannesKaufmann/html-to-markdown" 17 "github.com/JohannesKaufmann/html-to-markdown/plugin" 18 "github.com/PuerkitoBio/goquery" 19 "github.com/go-shiori/go-readability" 20 ) 21 22 func LoadLinkedArticle(url string) tea.Cmd { 23 return func() tea.Msg { 24 if url == "" { 25 return utils.NoExternalURL{} 26 } 27 28 title, article, err := getArticle(url) 29 if err != nil { 30 return utils.Error{} 31 } 32 33 header := getReaderModeMetaBlock(title, url) 34 35 renderer, err := glamour.NewTermRenderer(glamour.WithStyles(ui.GlamourConfig)) 36 if err != nil { 37 return utils.Error{} 38 } 39 40 markdown, err := renderer.Render(article) 41 if err != nil { 42 return utils.Error{} 43 } 44 markdown = gloss.NewStyle().MarginLeft(2).Render(markdown) 45 46 renderedArticle := header + markdown 47 48 command := exec.Command("less", 49 "--RAW-CONTROL-CHARS", 50 "--ignore-case", 51 "--tilde", 52 "--use-color", 53 "-P?e"+ui.Prompt().Render("End"), 54 "-DSy", 55 "-DP-") 56 command.Stdin = strings.NewReader(renderedArticle) 57 58 return utils.RunCommand(command) 59 } 60 } 61 62 func getArticle(url string) (string, string, error) { 63 article, err := readability.FromURL(url, time.Second*5) 64 if err != nil { 65 return "", "", err 66 } 67 68 href := md.Rule{ 69 Filter: []string{"a"}, 70 Replacement: func(content string, selec *goquery.Selection, _ *md.Options) *string { 71 link, ok := selec.Attr("href") 72 if !ok { 73 return md.String(strings.TrimSpace(content)) 74 } 75 76 return md.String(fmt.Sprintf("[%s](%s)", strings.TrimSpace(content), link)) 77 }, 78 } 79 80 converter := md.NewConverter("", true, &md.Options{}) 81 converter.AddRules(href) 82 converter.Use(plugin.Table()) 83 84 markdown, err := converter.ConvertString(article.Content) 85 if err != nil { 86 return "", "", err 87 } 88 89 return article.Title, markdown, nil 90 }