97 lines
1.8 KiB
Go
97 lines
1.8 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"html/template"
|
|
"io/ioutil"
|
|
"net/http"
|
|
"path"
|
|
"strings"
|
|
"sync"
|
|
|
|
"github.com/ghodss/yaml"
|
|
"github.com/gomarkdown/markdown"
|
|
"github.com/gomarkdown/markdown/parser"
|
|
"go.uber.org/multierr"
|
|
)
|
|
|
|
var (
|
|
mu sync.RWMutex
|
|
)
|
|
|
|
type Config struct {
|
|
Modules []*Module
|
|
}
|
|
|
|
type Module struct {
|
|
Import string `json:"import"`
|
|
Repository string `json:"repository"`
|
|
Readme string `json:"readme"`
|
|
ReadmeHTML template.HTML `json:"-"`
|
|
}
|
|
|
|
func (m *Module) LoadReadme() error {
|
|
if m.Readme == "" {
|
|
m.Readme = m.Repository + "/raw/master/README.md"
|
|
}
|
|
if !strings.HasPrefix(m.Readme, "http") {
|
|
m.Readme = "https://" + m.Readme
|
|
}
|
|
res, err := http.Get(m.Readme)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer res.Body.Close()
|
|
if res.StatusCode > 300 {
|
|
return fmt.Errorf("request failed: %s (%d)", res.Status, res.StatusCode)
|
|
}
|
|
b, err := ioutil.ReadAll(res.Body)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
extensions := parser.CommonExtensions | parser.AutoHeadingIDs
|
|
mdParser := parser.NewWithExtensions(extensions)
|
|
m.ReadmeHTML = template.HTML(markdown.ToHTML(b, mdParser, nil))
|
|
return nil
|
|
}
|
|
|
|
func NewModules(path string) (Modules, error) {
|
|
b, err := ioutil.ReadFile(path)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
c := &Config{}
|
|
if err := yaml.Unmarshal(b, c); err != nil {
|
|
return nil, err
|
|
}
|
|
return c.Modules, nil
|
|
}
|
|
|
|
type Modules []*Module
|
|
|
|
func (m *Modules) Find(name string) (*Module, bool) {
|
|
for _, v := range *m {
|
|
mod := path.Base(v.Import)
|
|
if mod == name {
|
|
return v, true
|
|
}
|
|
}
|
|
return nil, false
|
|
}
|
|
|
|
func (m *Modules) LoadReadme() error {
|
|
mu.Lock()
|
|
defer mu.Unlock()
|
|
errs := make(chan error, len(*m))
|
|
for _, v := range *m {
|
|
go func(mod *Module) {
|
|
errs <- mod.LoadReadme()
|
|
}(v)
|
|
}
|
|
var err error
|
|
for range *m {
|
|
err = multierr.Append(err, <-errs)
|
|
}
|
|
return err
|
|
}
|