Commit 7224ece
Eric Bower
·
2023-08-19 12:52:22 -0400 EDT
parent 8d0c699
feat: nested tree folder structure This feature is designed to support a folder/file structure that most people are familiar with. Instead of just having every single file in a large list, we nest files inside of folders. The main benefit here is that for large repos with a lot of files we don't ask end-users to download a massive MB tree file. It's more clicking -- which I don't like -- but this seems necessary when there are 10k+ files in a project.
5 files changed,
+272,
-89
+29,
-2
| ... | ... | @@ -1,10 +1,37 @@ | |
| 1 | 1 | {{template "base" .}} | |
| 2 | - | {{define "title"}}{{.Path}}@{{.RevData.Name}}{{end}} | |
| 2 | + | {{define "title"}}{{.Item.Path}}@{{.RevData.Name}}{{end}} | |
| 3 | 3 | {{define "meta"}} | |
| 4 | 4 | <link rel="stylesheet" href="/syntax.css" /> | |
| 5 | 5 | {{end}} | |
| 6 | 6 | ||
| 7 | 7 | {{define "content"}} | |
| 8 | - | <h2 class="text-lg">{{.Path}}</h2> | |
| 8 | + | <div class="text-md"> | |
| 9 | + | {{range .Item.Crumbs}} | |
| 10 | + | <a href="{{.URL}}">{{.Text}}</a> {{if .IsLast}}{{else}}/{{end}} | |
| 11 | + | {{end}} | |
| 12 | + | </div> | |
| 13 | + | ||
| 14 | + | {{if .Repo.HideTreeLastCommit}} | |
| 15 | + | {{else}} | |
| 16 | + | <div class="box"> | |
| 17 | + | <div class="flex items-center justify-between"> | |
| 18 | + | <div class="flex-1"> | |
| 19 | + | <a href="{{.Item.CommitURL}}">{{.Item.Summary}}</a> | |
| 20 | + | </div> | |
| 21 | + | <div> | |
| 22 | + | <a href="{{.Item.CommitURL}}">{{.Item.CommitID}}</a> | |
| 23 | + | </div> | |
| 24 | + | </div> | |
| 25 | + | ||
| 26 | + | <div class="flex items-center gap-xs"> | |
| 27 | + | <span>{{.Item.Author.Name}}</span> | |
| 28 | + | <span>·</span> | |
| 29 | + | <span>{{.Item.When}}</span> | |
| 30 | + | </div> | |
| 31 | + | </div> | |
| 32 | + | {{end}} | |
| 33 | + | ||
| 34 | + | <h2 class="text-lg">{{.Item.Name}}</h2> | |
| 35 | + | ||
| 9 | 36 | {{.Contents}} | |
| 10 | 37 | {{end }} |
+5,
-5
| ... | ... | @@ -5,12 +5,12 @@ | |
| 5 | 5 | ||
| 6 | 6 | {{define "content"}} | |
| 7 | 7 | <div> | |
| 8 | + | <div><span class="font-bold">({{.NumCommits}})</span> commits</div> | |
| 8 | 9 | {{range .Logs}} | |
| 9 | 10 | <div class="box"> | |
| 10 | 11 | <div class="flex justify-between items-center"> | |
| 11 | - | <div> | |
| 12 | - | <a href="{{.URL}}">{{.SummaryStr}}</a> | |
| 13 | - | </div> | |
| 12 | + | <a href="{{.URL}}" class="text-md">{{.SummaryStr}}</a> | |
| 13 | + | ||
| 14 | 14 | <div class="flex gap"> | |
| 15 | 15 | {{.ShortID}} | |
| 16 | 16 |
| ... | ... | @@ -24,9 +24,9 @@ | |
| 24 | 24 | </div> | |
| 25 | 25 | </div> | |
| 26 | 26 | ||
| 27 | - | <div class="flex items-center"> | |
| 27 | + | <div class="flex items-center gap-xs"> | |
| 28 | 28 | <span>{{.AuthorStr}}</span> | |
| 29 | - | <span> committed </span> | |
| 29 | + | <span>·</span> | |
| 30 | 30 | <span>{{.WhenStr}}</span> | |
| 31 | 31 | </div> | |
| 32 | 32 |
+28,
-15
| ... | ... | @@ -5,24 +5,37 @@ | |
| 5 | 5 | ||
| 6 | 6 | {{define "content"}} | |
| 7 | 7 | <div> | |
| 8 | - | {{range .Tree}} | |
| 9 | - | <div class="flex justify-between items-center gap my-sm border-b"> | |
| 10 | - | <div class="flex-1 tree-path"> | |
| 11 | - | <a href="{{.URL}}">{{.Path}}</a> | |
| 12 | - | </div> | |
| 13 | - | ||
| 14 | - | <div class="flex items-center gap"> | |
| 15 | - | {{if $.Repo.HideTreeLastCommit}} | |
| 8 | + | <div class="text-md mb"> | |
| 9 | + | {{range .Tree.Crumbs}} | |
| 10 | + | {{if .IsLast}} | |
| 11 | + | <span class="font-bold">{{.Text}}</span> | |
| 16 | 12 | {{else}} | |
| 17 | - | <div class="flex-1 tree-commit"> | |
| 18 | - | <a href="{{.CommitURL}}" title="{{.Summary}}">{{.When}}</a> | |
| 19 | - | </div> | |
| 13 | + | <a href="{{.URL}}">{{.Text}}</a> {{if .IsLast}}{{else}}/{{end}} | |
| 20 | 14 | {{end}} | |
| 21 | - | <div class="tree-size"> | |
| 22 | - | {{if .IsTextFile}}{{.NumLines}} L{{else}}{{.Size}}{{end}} | |
| 15 | + | {{end}} | |
| 16 | + | </div> | |
| 17 | + | ||
| 18 | + | {{range .Tree.Items}} | |
| 19 | + | <div class="flex justify-between items-center gap p-sm border-b tree-row"> | |
| 20 | + | <div class="flex-1 tree-path"> | |
| 21 | + | <a href="{{.URL}}">{{.Name}}{{if .IsDir}}/{{end}}</a> | |
| 22 | + | </div> | |
| 23 | + | ||
| 24 | + | <div class="flex items-center gap"> | |
| 25 | + | {{if $.Repo.HideTreeLastCommit}} | |
| 26 | + | {{else}} | |
| 27 | + | <div class="flex-1 tree-commit"> | |
| 28 | + | <a href="{{.CommitURL}}" title="{{.Summary}}">{{.When}}</a> | |
| 29 | + | </div> | |
| 30 | + | {{end}} | |
| 31 | + | <div class="tree-size"> | |
| 32 | + | {{if .IsDir}} | |
| 33 | + | {{else}} | |
| 34 | + | {{if .IsTextFile}}{{.NumLines}} L{{else}}{{.Size}}{{end}} | |
| 35 | + | {{end}} | |
| 36 | + | </div> | |
| 23 | 37 | </div> | |
| 24 | 38 | </div> | |
| 25 | - | </div> | |
| 26 | - | {{end}} | |
| 39 | + | {{end}} | |
| 27 | 40 | </div> | |
| 28 | 41 | {{end}} |
M
main.go
+193,
-66
| ... | ... | @@ -117,14 +117,19 @@ type CommitData struct { | |
| 117 | 117 | ||
| 118 | 118 | type TreeItem struct { | |
| 119 | 119 | IsTextFile bool | |
| 120 | + | IsDir bool | |
| 120 | 121 | Size string | |
| 121 | 122 | NumLines int | |
| 123 | + | Name string | |
| 122 | 124 | Path string | |
| 123 | 125 | URL template.URL | |
| 126 | + | CommitID string | |
| 124 | 127 | CommitURL template.URL | |
| 125 | 128 | Summary string | |
| 126 | 129 | When string | |
| 130 | + | Author *git.Signature | |
| 127 | 131 | Entry *git.TreeEntry | |
| 132 | + | Crumbs []*Breadcrumb | |
| 128 | 133 | } | |
| 129 | 134 | ||
| 130 | 135 | type DiffRender struct { |
| ... | ... | @@ -176,18 +181,19 @@ type SummaryPageData struct { | |
| 176 | 181 | ||
| 177 | 182 | type TreePageData struct { | |
| 178 | 183 | *PageData | |
| 179 | - | Tree []*TreeItem | |
| 184 | + | Tree *TreeRoot | |
| 180 | 185 | } | |
| 181 | 186 | ||
| 182 | 187 | type LogPageData struct { | |
| 183 | 188 | *PageData | |
| 184 | - | Logs []*CommitData | |
| 189 | + | NumCommits int | |
| 190 | + | Logs []*CommitData | |
| 185 | 191 | } | |
| 186 | 192 | ||
| 187 | 193 | type FilePageData struct { | |
| 188 | 194 | *PageData | |
| 189 | 195 | Contents template.HTML | |
| 190 | - | Path string | |
| 196 | + | Item *TreeItem | |
| 191 | 197 | } | |
| 192 | 198 | ||
| 193 | 199 | type CommitPageData struct { |
| ... | ... | @@ -347,11 +353,11 @@ func (c *Config) writeRootSummary(data *PageData, readme template.HTML) { | |
| 347 | 353 | }) | |
| 348 | 354 | } | |
| 349 | 355 | ||
| 350 | - | func (c *Config) writeTree(data *PageData, tree []*TreeItem) { | |
| 351 | - | c.Logger.Infof("writing tree (%s)", data.RevData.Name()) | |
| 356 | + | func (c *Config) writeTree(data *PageData, tree *TreeRoot) { | |
| 357 | + | c.Logger.Infof("writing tree (%s)", tree.Path) | |
| 352 | 358 | c.writeHtml(&WriteData{ | |
| 353 | 359 | Filename: "index.html", | |
| 354 | - | Subdir: getTreeBaseDir(data.RevData), | |
| 360 | + | Subdir: tree.Path, | |
| 355 | 361 | Template: "html/tree.page.tmpl", | |
| 356 | 362 | Data: &TreePageData{ | |
| 357 | 363 | PageData: data, |
| ... | ... | @@ -367,8 +373,9 @@ func (c *Config) writeLog(data *PageData, logs []*CommitData) { | |
| 367 | 373 | Subdir: getLogBaseDir(data.RevData), | |
| 368 | 374 | Template: "html/log.page.tmpl", | |
| 369 | 375 | Data: &LogPageData{ | |
| 370 | - | PageData: data, | |
| 371 | - | Logs: logs, | |
| 376 | + | PageData: data, | |
| 377 | + | NumCommits: len(logs), | |
| 378 | + | Logs: logs, | |
| 372 | 379 | }, | |
| 373 | 380 | }) | |
| 374 | 381 | } |
| ... | ... | @@ -414,7 +421,7 @@ func (c *Config) writeHTMLTreeFile(pageData *PageData, treeItem *TreeItem) strin | |
| 414 | 421 | Data: &FilePageData{ | |
| 415 | 422 | PageData: pageData, | |
| 416 | 423 | Contents: template.HTML(contents), | |
| 417 | - | Path: treeItem.Path, | |
| 424 | + | Item: treeItem, | |
| 418 | 425 | }, | |
| 419 | 426 | Subdir: getFileURL(pageData.RevData, d), | |
| 420 | 427 | }) |
| ... | ... | @@ -522,8 +529,12 @@ func getLogBaseDir(info RevInfo) string { | |
| 522 | 529 | return filepath.Join("/", "logs", subdir) | |
| 523 | 530 | } | |
| 524 | 531 | ||
| 532 | + | func getFileBaseDir(info RevInfo) string { | |
| 533 | + | return filepath.Join(getTreeBaseDir(info), "item") | |
| 534 | + | } | |
| 535 | + | ||
| 525 | 536 | func getFileURL(info RevInfo, fname string) string { | |
| 526 | - | return filepath.Join(getTreeBaseDir(info), "item", fname) | |
| 537 | + | return filepath.Join(getFileBaseDir(info), fname) | |
| 527 | 538 | } | |
| 528 | 539 | ||
| 529 | 540 | func getTreeURL(info RevInfo) template.URL { |
| ... | ... | @@ -672,33 +683,164 @@ func (c *Config) writeRepo() *BranchOutput { | |
| 672 | 683 | return mainOutput | |
| 673 | 684 | } | |
| 674 | 685 | ||
| 686 | + | type TreeRoot struct { | |
| 687 | + | Path string | |
| 688 | + | Items []*TreeItem | |
| 689 | + | Crumbs []*Breadcrumb | |
| 690 | + | } | |
| 691 | + | ||
| 675 | 692 | type TreeWalker struct { | |
| 676 | - | revData *RevData | |
| 677 | - | treeItem chan *TreeItem | |
| 693 | + | treeItem chan *TreeItem | |
| 694 | + | tree chan *TreeRoot | |
| 695 | + | HideTreeLastCommit bool | |
| 696 | + | PageData *PageData | |
| 697 | + | Repo *git.Repository | |
| 698 | + | } | |
| 699 | + | ||
| 700 | + | type Breadcrumb struct { | |
| 701 | + | Text string | |
| 702 | + | URL template.URL | |
| 703 | + | IsLast bool | |
| 704 | + | } | |
| 705 | + | ||
| 706 | + | func (tw *TreeWalker) calcBreadcrumbs(curpath string) []*Breadcrumb { | |
| 707 | + | if curpath == "" { | |
| 708 | + | return []*Breadcrumb{} | |
| 709 | + | } | |
| 710 | + | parts := strings.Split(curpath, string(os.PathSeparator)) | |
| 711 | + | rootURL := template.URL( | |
| 712 | + | filepath.Join( | |
| 713 | + | getTreeBaseDir(tw.PageData.RevData), | |
| 714 | + | "index.html", | |
| 715 | + | ), | |
| 716 | + | ) | |
| 717 | + | ||
| 718 | + | crumbs := make([]*Breadcrumb, len(parts)+1) | |
| 719 | + | crumbs[0] = &Breadcrumb { | |
| 720 | + | URL: rootURL, | |
| 721 | + | Text: tw.PageData.Repo.RepoName, | |
| 722 | + | } | |
| 723 | + | ||
| 724 | + | cur := "" | |
| 725 | + | for idx, d := range parts { | |
| 726 | + | crumbs[idx+1] = &Breadcrumb{ | |
| 727 | + | Text: d, | |
| 728 | + | URL: template.URL(filepath.Join(getFileBaseDir(tw.PageData.RevData), cur, d, "index.html")), | |
| 729 | + | } | |
| 730 | + | if idx == len(parts) - 1 { | |
| 731 | + | crumbs[idx+1].IsLast = true | |
| 732 | + | } | |
| 733 | + | cur = filepath.Join(cur, d) | |
| 734 | + | } | |
| 735 | + | ||
| 736 | + | return crumbs | |
| 737 | + | } | |
| 738 | + | ||
| 739 | + | func (tw *TreeWalker) NewTreeItem(entry *git.TreeEntry, curpath string, crumbs []*Breadcrumb) *TreeItem { | |
| 740 | + | typ := entry.Type() | |
| 741 | + | fname := filepath.Join(curpath, entry.Name()) | |
| 742 | + | item := &TreeItem{ | |
| 743 | + | Size: toPretty(entry.Size()), | |
| 744 | + | Name: entry.Name(), | |
| 745 | + | Path: fname, | |
| 746 | + | Entry: entry, | |
| 747 | + | URL: template.URL(getFileURL(tw.PageData.RevData, fname)), | |
| 748 | + | Crumbs: crumbs, | |
| 749 | + | } | |
| 750 | + | ||
| 751 | + | // `git rev-list` is pretty expensive here, so we have a flag to disable | |
| 752 | + | if tw.HideTreeLastCommit { | |
| 753 | + | // c.Logger.Info("skipping the process of finding the last commit for each file") | |
| 754 | + | } else { | |
| 755 | + | id := tw.PageData.RevData.ID() | |
| 756 | + | lastCommits, err := tw.Repo.RevList([]string{id}, git.RevListOptions{ | |
| 757 | + | Path: item.Path, | |
| 758 | + | CommandOptions: git.CommandOptions{Args: []string{"-1"}}, | |
| 759 | + | }) | |
| 760 | + | bail(err) | |
| 761 | + | ||
| 762 | + | var lc *git.Commit | |
| 763 | + | if len(lastCommits) > 0 { | |
| 764 | + | lc = lastCommits[0] | |
| 765 | + | } | |
| 766 | + | item.CommitURL = getCommitURL(lc.ID.String()) | |
| 767 | + | item.CommitID = getShortID(lc.ID.String()) | |
| 768 | + | item.Summary = lc.Summary() | |
| 769 | + | item.When = lc.Author.When.Format("02 Jan 06") | |
| 770 | + | item.Author = lc.Author | |
| 771 | + | } | |
| 772 | + | ||
| 773 | + | fpath := getFileURL( | |
| 774 | + | tw.PageData.RevData, | |
| 775 | + | fmt.Sprintf("%s.html", fname), | |
| 776 | + | ) | |
| 777 | + | if typ == git.ObjectTree { | |
| 778 | + | item.IsDir = true | |
| 779 | + | fpath = filepath.Join( | |
| 780 | + | getFileBaseDir(tw.PageData.RevData), | |
| 781 | + | curpath, | |
| 782 | + | entry.Name(), | |
| 783 | + | "index.html", | |
| 784 | + | ) | |
| 785 | + | } | |
| 786 | + | item.URL = template.URL(fpath) | |
| 787 | + | ||
| 788 | + | return item | |
| 678 | 789 | } | |
| 679 | 790 | ||
| 680 | 791 | func (tw *TreeWalker) walk(tree *git.Tree, curpath string) { | |
| 681 | 792 | entries, err := tree.Entries() | |
| 682 | 793 | bail(err) | |
| 683 | 794 | ||
| 795 | + | crumbs := tw.calcBreadcrumbs(curpath) | |
| 796 | + | treeEntries := []*TreeItem{} | |
| 684 | 797 | for _, entry := range entries { | |
| 685 | - | fname := filepath.Join(curpath, entry.Name()) | |
| 686 | 798 | typ := entry.Type() | |
| 799 | + | item := tw.NewTreeItem(entry, curpath, crumbs) | |
| 687 | 800 | ||
| 688 | 801 | if typ == git.ObjectTree { | |
| 802 | + | item.IsDir = true | |
| 689 | 803 | re, _ := tree.Subtree(entry.Name()) | |
| 690 | - | tw.walk(re, fname) | |
| 804 | + | tw.walk(re, item.Path) | |
| 805 | + | treeEntries = append(treeEntries, item) | |
| 806 | + | tw.treeItem <- item | |
| 691 | 807 | } else if typ == git.ObjectBlob { | |
| 692 | - | tw.treeItem <- &TreeItem{ | |
| 693 | - | Size: toPretty(entry.Size()), | |
| 694 | - | Path: fname, | |
| 695 | - | Entry: entry, | |
| 696 | - | URL: template.URL(getFileURL(tw.revData, fname)), | |
| 697 | - | } | |
| 808 | + | treeEntries = append(treeEntries, item) | |
| 809 | + | tw.treeItem <- item | |
| 698 | 810 | } | |
| 699 | 811 | } | |
| 700 | 812 | ||
| 813 | + | sort.Slice(treeEntries, func(i, j int) bool { | |
| 814 | + | nameI := treeEntries[i].Name | |
| 815 | + | nameJ := treeEntries[j].Name | |
| 816 | + | if treeEntries[i].IsDir && treeEntries[j].IsDir { | |
| 817 | + | return nameI < nameJ | |
| 818 | + | } | |
| 819 | + | ||
| 820 | + | if treeEntries[i].IsDir && !treeEntries[j].IsDir { | |
| 821 | + | return true | |
| 822 | + | } | |
| 823 | + | ||
| 824 | + | return nameI < nameJ | |
| 825 | + | }) | |
| 826 | + | ||
| 827 | + | fpath := filepath.Join( | |
| 828 | + | getFileBaseDir(tw.PageData.RevData), | |
| 829 | + | curpath, | |
| 830 | + | ) | |
| 831 | + | // root gets a special spot outside of `item` subdir | |
| 701 | 832 | if curpath == "" { | |
| 833 | + | fpath = getTreeBaseDir(tw.PageData.RevData) | |
| 834 | + | } | |
| 835 | + | ||
| 836 | + | tw.tree <- &TreeRoot{ | |
| 837 | + | Path: fpath, | |
| 838 | + | Items: treeEntries, | |
| 839 | + | Crumbs: crumbs, | |
| 840 | + | } | |
| 841 | + | ||
| 842 | + | if curpath == "" { | |
| 843 | + | close(tw.tree) | |
| 702 | 844 | close(tw.treeItem) | |
| 703 | 845 | } | |
| 704 | 846 | } |
| ... | ... | @@ -773,12 +915,14 @@ func (c *Config) writeRevision(repo *git.Repository, pageData *PageData, refs [] | |
| 773 | 915 | tree, err := repo.LsTree(pageData.RevData.ID()) | |
| 774 | 916 | bail(err) | |
| 775 | 917 | ||
| 776 | - | treeEntries := []*TreeItem{} | |
| 777 | 918 | readme := "" | |
| 778 | 919 | entries := make(chan *TreeItem) | |
| 920 | + | subtrees := make(chan *TreeRoot) | |
| 779 | 921 | tw := &TreeWalker{ | |
| 780 | - | revData: pageData.RevData, | |
| 922 | + | PageData: pageData, | |
| 923 | + | Repo: repo, | |
| 781 | 924 | treeItem: entries, | |
| 925 | + | tree: subtrees, | |
| 782 | 926 | } | |
| 783 | 927 | wg.Add(1) | |
| 784 | 928 | go func() { |
| ... | ... | @@ -786,62 +930,45 @@ func (c *Config) writeRevision(repo *git.Repository, pageData *PageData, refs [] | |
| 786 | 930 | tw.walk(tree, "") | |
| 787 | 931 | }() | |
| 788 | 932 | ||
| 789 | - | for e := range entries { | |
| 790 | - | wg.Add(1) | |
| 791 | - | go func(entry *TreeItem) { | |
| 792 | - | defer wg.Done() | |
| 793 | - | entry.Path = strings.TrimPrefix(entry.Path, "/") | |
| 794 | - | ||
| 795 | - | var lastCommits []*git.Commit | |
| 796 | - | // `git rev-list` is pretty expensive here, so we have a flag to disable | |
| 797 | - | if pageData.Repo.HideTreeLastCommit { | |
| 798 | - | // c.Logger.Info("skipping the process of finding the last commit for each file") | |
| 799 | - | } else { | |
| 800 | - | lastCommits, err = repo.RevList([]string{pageData.RevData.ID()}, git.RevListOptions{ | |
| 801 | - | Path: entry.Path, | |
| 802 | - | CommandOptions: git.CommandOptions{Args: []string{"-1"}}, | |
| 803 | - | }) | |
| 804 | - | bail(err) | |
| 805 | - | ||
| 806 | - | var lc *git.Commit | |
| 807 | - | if len(lastCommits) > 0 { | |
| 808 | - | lc = lastCommits[0] | |
| 933 | + | wg.Add(1) | |
| 934 | + | go func() { | |
| 935 | + | defer wg.Done() | |
| 936 | + | for e := range entries { | |
| 937 | + | wg.Add(1) | |
| 938 | + | go func(entry *TreeItem) { | |
| 939 | + | defer wg.Done() | |
| 940 | + | if entry.IsDir { | |
| 941 | + | return | |
| 809 | 942 | } | |
| 810 | - | entry.CommitURL = getCommitURL(lc.ID.String()) | |
| 811 | - | entry.Summary = lc.Summary() | |
| 812 | - | entry.When = lc.Author.When.Format("02 Jan 06") | |
| 813 | - | } | |
| 814 | 943 | ||
| 815 | - | fpath := getFileURL( | |
| 816 | - | pageData.RevData, | |
| 817 | - | fmt.Sprintf("%s.html", entry.Path), | |
| 818 | - | ) | |
| 819 | - | entry.URL = template.URL(fpath) | |
| 944 | + | readmeStr := c.writeHTMLTreeFile(pageData, entry) | |
| 945 | + | if readmeStr != "" { | |
| 946 | + | readme = readmeStr | |
| 947 | + | } | |
| 948 | + | }(e) | |
| 949 | + | } | |
| 950 | + | }() | |
| 820 | 951 | ||
| 821 | - | readmeStr := c.writeHTMLTreeFile(pageData, entry) | |
| 822 | - | if readmeStr != "" { | |
| 823 | - | readme = readmeStr | |
| 824 | - | } | |
| 825 | - | treeEntries = append(treeEntries, entry) | |
| 826 | - | }(e) | |
| 827 | - | } | |
| 952 | + | wg.Add(1) | |
| 953 | + | go func() { | |
| 954 | + | defer wg.Done() | |
| 955 | + | for t := range subtrees { | |
| 956 | + | wg.Add(1) | |
| 957 | + | go func(tree *TreeRoot) { | |
| 958 | + | defer wg.Done() | |
| 959 | + | c.writeTree(pageData, tree) | |
| 960 | + | }(t) | |
| 961 | + | } | |
| 962 | + | }() | |
| 828 | 963 | ||
| 829 | 964 | wg.Wait() | |
| 830 | 965 | ||
| 831 | - | sort.Slice(treeEntries, func(i, j int) bool { | |
| 832 | - | nameI := treeEntries[i].Path | |
| 833 | - | nameJ := treeEntries[j].Path | |
| 834 | - | return nameI < nameJ | |
| 835 | - | }) | |
| 836 | - | ||
| 837 | 966 | c.Logger.Infof( | |
| 838 | 967 | "compilation complete (%s) branch (%s)", | |
| 839 | 968 | c.RepoName, | |
| 840 | 969 | pageData.RevData.Name(), | |
| 841 | 970 | ) | |
| 842 | 971 | ||
| 843 | - | c.writeTree(pageData, treeEntries) | |
| 844 | - | ||
| 845 | 972 | output.Readme = readme | |
| 846 | 973 | return output | |
| 847 | 974 | } |
+17,
-1
| ... | ... | @@ -140,7 +140,7 @@ hr { | |
| 140 | 140 | margin: 0; | |
| 141 | 141 | height: 1px; | |
| 142 | 142 | background: var(--grey); | |
| 143 | - | margin: 2rem auto; | |
| 143 | + | margin: 1rem auto; | |
| 144 | 144 | text-align: center; | |
| 145 | 145 | } | |
| 146 | 146 |
| ... | ... | @@ -314,6 +314,10 @@ figure { | |
| 314 | 314 | margin-top: 0.5rem; | |
| 315 | 315 | } | |
| 316 | 316 | ||
| 317 | + | .mb { | |
| 318 | + | margin-bottom: 0.5rem; | |
| 319 | + | } | |
| 320 | + | ||
| 317 | 321 | .mt-lg { | |
| 318 | 322 | margin-top: 1.35rem; | |
| 319 | 323 | } |
| ... | ... | @@ -343,6 +347,10 @@ figure { | |
| 343 | 347 | margin-right: 1rem; | |
| 344 | 348 | } | |
| 345 | 349 | ||
| 350 | + | .p-sm { | |
| 351 | + | padding: 0.5rem; | |
| 352 | + | } | |
| 353 | + | ||
| 346 | 354 | .justify-between { | |
| 347 | 355 | justify-content: space-between; | |
| 348 | 356 | } |