package projects import ( "encoding/json" "html/template" "log" "math" "os" "path" "strings" ) type Link struct { Title string Href string Class string `json:",omitempty"` } type Project struct { Name string `json:"-"` Title string Description string Shortdesc string GoGet string `json:",omitempty"` ReadmePath string `json:",omitempty"` Git string `json:",omitempty"` // local git repo License string `json:",omitempty"` Links []Link Tags []string dir string `json:"-"` FormattedReadme template.HTML `json:"-"` } func LoadProject(name string) (p Project, err error) { f, err := os.Open(name) if err != nil { return p, err } defer f.Close() dec := json.NewDecoder(f) if err := dec.Decode(&p); err != nil { return p, err } p.dir = path.Dir(name) p.formatReadme() nameParts := strings.Split(path.Base(name), ".") p.Name = strings.Join(nameParts[:len(nameParts)-1], ".") return } type ProjectRepo struct { Dir string Projects map[string]Project Tags map[string]map[string]struct{} Tagcloud map[string]TagcloudElem } const TAGCLOUD_SIZE_CATEGORIES = 5 type TagcloudElem struct { Tag string Size int } func NewProjectRepo(dir string) *ProjectRepo { return &ProjectRepo{ Dir: dir, Projects: make(map[string]Project), Tags: make(map[string]map[string]struct{}), Tagcloud: make(map[string]TagcloudElem), } } func (repo *ProjectRepo) updateTags() { tags := make(map[string]map[string]struct{}) tagcounts := make(map[string]int) maxcount := 0 for name, proj := range repo.Projects { for _, tag := range proj.Tags { if _, ok := tags[tag]; !ok { tags[tag] = make(map[string]struct{}) } tags[tag][name] = struct{}{} tagcount := tagcounts[tag] + 1 tagcounts[tag] = tagcount if tagcount > maxcount { maxcount = tagcount } } } tagcloud := make(map[string]TagcloudElem) if maxcount > 0 { for tag, count := range tagcounts { tagcloud[tag] = TagcloudElem{ Tag: tag, Size: int(math.Ceil((float64(count) / float64(maxcount)) * TAGCLOUD_SIZE_CATEGORIES)), } } } repo.Tags = tags repo.Tagcloud = tagcloud } func (repo *ProjectRepo) ScanProjects() { d, err := os.Open(repo.Dir) if err != nil { log.Printf("Failed scanning projects: Could not open dir: %s", err) return } defer d.Close() names, err := d.Readdirnames(0) if err != nil { log.Printf("Failed scanning projects: Could not readdir: %s", err) return } projects := make(map[string]Project) for _, fname := range names { if path.Ext(fname) != ".json" { continue } p, err := LoadProject(path.Join(repo.Dir, fname)) if err != nil { log.Printf("Skip project file %s: %s", fname, err) continue } projects[p.Name] = p } repo.Projects = projects repo.updateTags() }