+2
.gitignore
+2
.gitignore
+49
-8
appview/pages/markup/markdown.go
+49
-8
appview/pages/markup/markdown.go
···
3
4
import (
5
"bytes"
6
"path"
7
8
"github.com/yuin/goldmark"
···
11
"github.com/yuin/goldmark/parser"
12
"github.com/yuin/goldmark/text"
13
"github.com/yuin/goldmark/util"
14
)
15
16
// RendererType defines the type of renderer to use based on context
···
24
// RenderContext holds the contextual data for rendering markdown.
25
// It can be initialized empty, and that'll skip any transformations.
26
type RenderContext struct {
27
-
Ref string
28
-
FullRepoName string
29
RendererType RendererType
30
}
31
···
66
67
switch a.rctx.RendererType {
68
case RendererTypeRepoMarkdown:
69
-
if v, ok := n.(*ast.Link); ok {
70
-
a.rctx.relativeLinkTransformer(v)
71
}
72
// more types here like RendererTypeIssue/Pull etc.
73
}
···
79
func (rctx *RenderContext) relativeLinkTransformer(link *ast.Link) {
80
dst := string(link.Destination)
81
82
-
if len(dst) == 0 || dst[0] == '#' ||
83
-
bytes.Contains(link.Destination, []byte("://")) ||
84
-
bytes.HasPrefix(link.Destination, []byte("mailto:")) {
85
return
86
}
87
88
-
newPath := path.Join("/", rctx.FullRepoName, "tree", rctx.Ref, dst)
89
link.Destination = []byte(newPath)
90
}
···
3
4
import (
5
"bytes"
6
+
"net/url"
7
"path"
8
9
"github.com/yuin/goldmark"
···
12
"github.com/yuin/goldmark/parser"
13
"github.com/yuin/goldmark/text"
14
"github.com/yuin/goldmark/util"
15
+
"tangled.sh/tangled.sh/core/appview/pages/repoinfo"
16
)
17
18
// RendererType defines the type of renderer to use based on context
···
26
// RenderContext holds the contextual data for rendering markdown.
27
// It can be initialized empty, and that'll skip any transformations.
28
type RenderContext struct {
29
+
repoinfo.RepoInfo
30
+
IsDev bool
31
RendererType RendererType
32
}
33
···
68
69
switch a.rctx.RendererType {
70
case RendererTypeRepoMarkdown:
71
+
switch n.(type) {
72
+
case *ast.Link:
73
+
a.rctx.relativeLinkTransformer(n.(*ast.Link))
74
+
case *ast.Image:
75
+
a.rctx.imageFromKnotTransformer(n.(*ast.Image))
76
}
77
// more types here like RendererTypeIssue/Pull etc.
78
}
···
84
func (rctx *RenderContext) relativeLinkTransformer(link *ast.Link) {
85
dst := string(link.Destination)
86
87
+
if isAbsoluteUrl(dst) {
88
return
89
}
90
91
+
newPath := path.Join("/", rctx.RepoInfo.FullName(), "tree", rctx.RepoInfo.Ref, dst)
92
link.Destination = []byte(newPath)
93
}
94
+
95
+
func (rctx *RenderContext) imageFromKnotTransformer(img *ast.Image) {
96
+
dst := string(img.Destination)
97
+
98
+
if isAbsoluteUrl(dst) {
99
+
return
100
+
}
101
+
102
+
// strip leading './'
103
+
if len(dst) >= 2 && dst[0:2] == "./" {
104
+
dst = dst[2:]
105
+
}
106
+
107
+
scheme := "https"
108
+
if rctx.IsDev {
109
+
scheme = "http"
110
+
}
111
+
parsedURL := &url.URL{
112
+
Scheme: scheme,
113
+
Host: rctx.Knot,
114
+
Path: path.Join("/",
115
+
rctx.RepoInfo.OwnerDid,
116
+
rctx.RepoInfo.Name,
117
+
"raw",
118
+
url.PathEscape(rctx.RepoInfo.Ref),
119
+
dst),
120
+
}
121
+
newPath := parsedURL.String()
122
+
img.Destination = []byte(newPath)
123
+
}
124
+
125
+
func isAbsoluteUrl(link string) bool {
126
+
parsed, err := url.Parse(link)
127
+
if err != nil {
128
+
return false
129
+
}
130
+
return parsed.IsAbs()
131
+
}
+44
-143
appview/pages/pages.go
+44
-143
appview/pages/pages.go
···
12
"log"
13
"net/http"
14
"os"
15
-
"path"
16
"path/filepath"
17
-
"slices"
18
"strings"
19
20
"tangled.sh/tangled.sh/core/appview/auth"
21
"tangled.sh/tangled.sh/core/appview/db"
22
"tangled.sh/tangled.sh/core/appview/pages/markup"
23
"tangled.sh/tangled.sh/core/appview/pagination"
24
-
"tangled.sh/tangled.sh/core/appview/state/userutil"
25
"tangled.sh/tangled.sh/core/patchutil"
26
"tangled.sh/tangled.sh/core/types"
27
···
42
dev bool
43
embedFS embed.FS
44
templateDir string // Path to templates on disk for dev mode
45
}
46
47
func NewPages(dev bool) *Pages {
48
p := &Pages{
49
t: make(map[string]*template.Template),
50
dev: dev,
51
embedFS: Files,
52
templateDir: "appview/pages",
53
}
54
···
293
type ForkRepoParams struct {
294
LoggedInUser *auth.User
295
Knots []string
296
-
RepoInfo RepoInfo
297
}
298
299
func (p *Pages) ForkRepo(w io.Writer, params ForkRepoParams) error {
···
343
}
344
345
type RepoDescriptionParams struct {
346
-
RepoInfo RepoInfo
347
}
348
349
func (p *Pages) EditRepoDescriptionFragment(w io.Writer, params RepoDescriptionParams) error {
···
354
return p.executePlain("repo/fragments/repoDescription", w, params)
355
}
356
357
-
type RepoInfo struct {
358
-
Name string
359
-
OwnerDid string
360
-
OwnerHandle string
361
-
Description string
362
-
Knot string
363
-
RepoAt syntax.ATURI
364
-
IsStarred bool
365
-
Stats db.RepoStats
366
-
Roles RolesInRepo
367
-
Source *db.Repo
368
-
SourceHandle string
369
-
Ref string
370
-
DisableFork bool
371
-
}
372
-
373
-
type RolesInRepo struct {
374
-
Roles []string
375
-
}
376
-
377
-
func (r RolesInRepo) SettingsAllowed() bool {
378
-
return slices.Contains(r.Roles, "repo:settings")
379
-
}
380
-
381
-
func (r RolesInRepo) CollaboratorInviteAllowed() bool {
382
-
return slices.Contains(r.Roles, "repo:invite")
383
-
}
384
-
385
-
func (r RolesInRepo) RepoDeleteAllowed() bool {
386
-
return slices.Contains(r.Roles, "repo:delete")
387
-
}
388
-
389
-
func (r RolesInRepo) IsOwner() bool {
390
-
return slices.Contains(r.Roles, "repo:owner")
391
-
}
392
-
393
-
func (r RolesInRepo) IsCollaborator() bool {
394
-
return slices.Contains(r.Roles, "repo:collaborator")
395
-
}
396
-
397
-
func (r RolesInRepo) IsPushAllowed() bool {
398
-
return slices.Contains(r.Roles, "repo:push")
399
-
}
400
-
401
-
func (r RepoInfo) OwnerWithAt() string {
402
-
if r.OwnerHandle != "" {
403
-
return fmt.Sprintf("@%s", r.OwnerHandle)
404
-
} else {
405
-
return r.OwnerDid
406
-
}
407
-
}
408
-
409
-
func (r RepoInfo) FullName() string {
410
-
return path.Join(r.OwnerWithAt(), r.Name)
411
-
}
412
-
413
-
func (r RepoInfo) OwnerWithoutAt() string {
414
-
if strings.HasPrefix(r.OwnerWithAt(), "@") {
415
-
return strings.TrimPrefix(r.OwnerWithAt(), "@")
416
-
} else {
417
-
return userutil.FlattenDid(r.OwnerDid)
418
-
}
419
-
}
420
-
421
-
func (r RepoInfo) FullNameWithoutAt() string {
422
-
return path.Join(r.OwnerWithoutAt(), r.Name)
423
-
}
424
-
425
-
func (r RepoInfo) GetTabs() [][]string {
426
-
tabs := [][]string{
427
-
{"overview", "/", "square-chart-gantt"},
428
-
{"issues", "/issues", "circle-dot"},
429
-
{"pulls", "/pulls", "git-pull-request"},
430
-
}
431
-
432
-
if r.Roles.SettingsAllowed() {
433
-
tabs = append(tabs, []string{"settings", "/settings", "cog"})
434
-
}
435
-
436
-
return tabs
437
-
}
438
-
439
-
// each tab on a repo could have some metadata:
440
-
//
441
-
// issues -> number of open issues etc.
442
-
// settings -> a warning icon to setup branch protection? idk
443
-
//
444
-
// we gather these bits of info here, because go templates
445
-
// are difficult to program in
446
-
func (r RepoInfo) TabMetadata() map[string]any {
447
-
meta := make(map[string]any)
448
-
449
-
if r.Stats.PullCount.Open > 0 {
450
-
meta["pulls"] = r.Stats.PullCount.Open
451
-
}
452
-
453
-
if r.Stats.IssueCount.Open > 0 {
454
-
meta["issues"] = r.Stats.IssueCount.Open
455
-
}
456
-
457
-
// more stuff?
458
-
459
-
return meta
460
-
}
461
-
462
type RepoIndexParams struct {
463
LoggedInUser *auth.User
464
-
RepoInfo RepoInfo
465
Active string
466
TagMap map[string][]string
467
CommitsTrunc []*object.Commit
···
479
return p.executeRepo("repo/empty", w, params)
480
}
481
482
-
rctx := markup.RenderContext{
483
-
Ref: params.RepoInfo.Ref,
484
-
FullRepoName: params.RepoInfo.FullName(),
485
}
486
487
if params.ReadmeFileName != "" {
···
489
ext := filepath.Ext(params.ReadmeFileName)
490
switch ext {
491
case ".md", ".markdown", ".mdown", ".mkdn", ".mkd":
492
-
htmlString = rctx.RenderMarkdown(params.Readme)
493
params.Raw = false
494
params.HTMLReadme = template.HTML(bluemonday.UGCPolicy().Sanitize(htmlString))
495
default:
···
504
505
type RepoLogParams struct {
506
LoggedInUser *auth.User
507
-
RepoInfo RepoInfo
508
TagMap map[string][]string
509
types.RepoLogResponse
510
Active string
···
518
519
type RepoCommitParams struct {
520
LoggedInUser *auth.User
521
-
RepoInfo RepoInfo
522
Active string
523
EmailToDidOrHandle map[string]string
524
···
532
533
type RepoTreeParams struct {
534
LoggedInUser *auth.User
535
-
RepoInfo RepoInfo
536
Active string
537
BreadCrumbs [][]string
538
BaseTreeLink string
···
568
569
type RepoBranchesParams struct {
570
LoggedInUser *auth.User
571
-
RepoInfo RepoInfo
572
Active string
573
types.RepoBranchesResponse
574
}
···
580
581
type RepoTagsParams struct {
582
LoggedInUser *auth.User
583
-
RepoInfo RepoInfo
584
Active string
585
types.RepoTagsResponse
586
}
···
592
593
type RepoBlobParams struct {
594
LoggedInUser *auth.User
595
-
RepoInfo RepoInfo
596
Active string
597
BreadCrumbs [][]string
598
ShowRendered bool
···
607
if params.ShowRendered {
608
switch markup.GetFormat(params.Path) {
609
case markup.FormatMarkdown:
610
-
rctx := markup.RenderContext{
611
-
Ref: params.RepoInfo.Ref,
612
-
FullRepoName: params.RepoInfo.FullName(),
613
RendererType: markup.RendererTypeRepoMarkdown,
614
}
615
-
params.RenderedContents = template.HTML(rctx.RenderMarkdown(params.Contents))
616
}
617
}
618
···
657
658
type RepoSettingsParams struct {
659
LoggedInUser *auth.User
660
-
RepoInfo RepoInfo
661
Collaborators []Collaborator
662
Active string
663
Branches []string
···
673
674
type RepoIssuesParams struct {
675
LoggedInUser *auth.User
676
-
RepoInfo RepoInfo
677
Active string
678
Issues []db.Issue
679
DidHandleMap map[string]string
···
688
689
type RepoSingleIssueParams struct {
690
LoggedInUser *auth.User
691
-
RepoInfo RepoInfo
692
Active string
693
Issue db.Issue
694
Comments []db.Comment
···
710
711
type RepoNewIssueParams struct {
712
LoggedInUser *auth.User
713
-
RepoInfo RepoInfo
714
Active string
715
}
716
···
721
722
type EditIssueCommentParams struct {
723
LoggedInUser *auth.User
724
-
RepoInfo RepoInfo
725
Issue *db.Issue
726
Comment *db.Comment
727
}
···
733
type SingleIssueCommentParams struct {
734
LoggedInUser *auth.User
735
DidHandleMap map[string]string
736
-
RepoInfo RepoInfo
737
Issue *db.Issue
738
Comment *db.Comment
739
}
···
744
745
type RepoNewPullParams struct {
746
LoggedInUser *auth.User
747
-
RepoInfo RepoInfo
748
Branches []types.Branch
749
Active string
750
}
···
756
757
type RepoPullsParams struct {
758
LoggedInUser *auth.User
759
-
RepoInfo RepoInfo
760
Pulls []*db.Pull
761
Active string
762
DidHandleMap map[string]string
···
788
789
type RepoSinglePullParams struct {
790
LoggedInUser *auth.User
791
-
RepoInfo RepoInfo
792
Active string
793
DidHandleMap map[string]string
794
Pull *db.Pull
···
804
type RepoPullPatchParams struct {
805
LoggedInUser *auth.User
806
DidHandleMap map[string]string
807
-
RepoInfo RepoInfo
808
Pull *db.Pull
809
Diff *types.NiceDiff
810
Round int
···
819
type RepoPullInterdiffParams struct {
820
LoggedInUser *auth.User
821
DidHandleMap map[string]string
822
-
RepoInfo RepoInfo
823
Pull *db.Pull
824
Round int
825
Interdiff *patchutil.InterdiffResult
···
831
}
832
833
type PullPatchUploadParams struct {
834
-
RepoInfo RepoInfo
835
}
836
837
func (p *Pages) PullPatchUploadFragment(w io.Writer, params PullPatchUploadParams) error {
···
839
}
840
841
type PullCompareBranchesParams struct {
842
-
RepoInfo RepoInfo
843
Branches []types.Branch
844
}
845
···
848
}
849
850
type PullCompareForkParams struct {
851
-
RepoInfo RepoInfo
852
Forks []db.Repo
853
}
854
···
857
}
858
859
type PullCompareForkBranchesParams struct {
860
-
RepoInfo RepoInfo
861
SourceBranches []types.Branch
862
TargetBranches []types.Branch
863
}
···
868
869
type PullResubmitParams struct {
870
LoggedInUser *auth.User
871
-
RepoInfo RepoInfo
872
Pull *db.Pull
873
SubmissionId int
874
}
···
879
880
type PullActionsParams struct {
881
LoggedInUser *auth.User
882
-
RepoInfo RepoInfo
883
Pull *db.Pull
884
RoundNumber int
885
MergeCheck types.MergeCheckResponse
···
892
893
type PullNewCommentParams struct {
894
LoggedInUser *auth.User
895
-
RepoInfo RepoInfo
896
Pull *db.Pull
897
RoundNumber int
898
}
···
12
"log"
13
"net/http"
14
"os"
15
"path/filepath"
16
"strings"
17
18
"tangled.sh/tangled.sh/core/appview/auth"
19
"tangled.sh/tangled.sh/core/appview/db"
20
"tangled.sh/tangled.sh/core/appview/pages/markup"
21
+
"tangled.sh/tangled.sh/core/appview/pages/repoinfo"
22
"tangled.sh/tangled.sh/core/appview/pagination"
23
"tangled.sh/tangled.sh/core/patchutil"
24
"tangled.sh/tangled.sh/core/types"
25
···
40
dev bool
41
embedFS embed.FS
42
templateDir string // Path to templates on disk for dev mode
43
+
rctx *markup.RenderContext
44
}
45
46
func NewPages(dev bool) *Pages {
47
+
// initialized with safe defaults, can be overriden per use
48
+
rctx := &markup.RenderContext{
49
+
IsDev: dev,
50
+
}
51
+
52
p := &Pages{
53
t: make(map[string]*template.Template),
54
dev: dev,
55
embedFS: Files,
56
+
rctx: rctx,
57
templateDir: "appview/pages",
58
}
59
···
298
type ForkRepoParams struct {
299
LoggedInUser *auth.User
300
Knots []string
301
+
RepoInfo repoinfo.RepoInfo
302
}
303
304
func (p *Pages) ForkRepo(w io.Writer, params ForkRepoParams) error {
···
348
}
349
350
type RepoDescriptionParams struct {
351
+
RepoInfo repoinfo.RepoInfo
352
}
353
354
func (p *Pages) EditRepoDescriptionFragment(w io.Writer, params RepoDescriptionParams) error {
···
359
return p.executePlain("repo/fragments/repoDescription", w, params)
360
}
361
362
type RepoIndexParams struct {
363
LoggedInUser *auth.User
364
+
RepoInfo repoinfo.RepoInfo
365
Active string
366
TagMap map[string][]string
367
CommitsTrunc []*object.Commit
···
379
return p.executeRepo("repo/empty", w, params)
380
}
381
382
+
p.rctx = &markup.RenderContext{
383
+
RepoInfo: params.RepoInfo,
384
+
IsDev: p.dev,
385
+
RendererType: markup.RendererTypeRepoMarkdown,
386
}
387
388
if params.ReadmeFileName != "" {
···
390
ext := filepath.Ext(params.ReadmeFileName)
391
switch ext {
392
case ".md", ".markdown", ".mdown", ".mkdn", ".mkd":
393
+
htmlString = p.rctx.RenderMarkdown(params.Readme)
394
params.Raw = false
395
params.HTMLReadme = template.HTML(bluemonday.UGCPolicy().Sanitize(htmlString))
396
default:
···
405
406
type RepoLogParams struct {
407
LoggedInUser *auth.User
408
+
RepoInfo repoinfo.RepoInfo
409
TagMap map[string][]string
410
types.RepoLogResponse
411
Active string
···
419
420
type RepoCommitParams struct {
421
LoggedInUser *auth.User
422
+
RepoInfo repoinfo.RepoInfo
423
Active string
424
EmailToDidOrHandle map[string]string
425
···
433
434
type RepoTreeParams struct {
435
LoggedInUser *auth.User
436
+
RepoInfo repoinfo.RepoInfo
437
Active string
438
BreadCrumbs [][]string
439
BaseTreeLink string
···
469
470
type RepoBranchesParams struct {
471
LoggedInUser *auth.User
472
+
RepoInfo repoinfo.RepoInfo
473
Active string
474
types.RepoBranchesResponse
475
}
···
481
482
type RepoTagsParams struct {
483
LoggedInUser *auth.User
484
+
RepoInfo repoinfo.RepoInfo
485
Active string
486
types.RepoTagsResponse
487
}
···
493
494
type RepoBlobParams struct {
495
LoggedInUser *auth.User
496
+
RepoInfo repoinfo.RepoInfo
497
Active string
498
BreadCrumbs [][]string
499
ShowRendered bool
···
508
if params.ShowRendered {
509
switch markup.GetFormat(params.Path) {
510
case markup.FormatMarkdown:
511
+
p.rctx = &markup.RenderContext{
512
+
RepoInfo: params.RepoInfo,
513
+
IsDev: p.dev,
514
RendererType: markup.RendererTypeRepoMarkdown,
515
}
516
+
params.RenderedContents = template.HTML(p.rctx.RenderMarkdown(params.Contents))
517
}
518
}
519
···
558
559
type RepoSettingsParams struct {
560
LoggedInUser *auth.User
561
+
RepoInfo repoinfo.RepoInfo
562
Collaborators []Collaborator
563
Active string
564
Branches []string
···
574
575
type RepoIssuesParams struct {
576
LoggedInUser *auth.User
577
+
RepoInfo repoinfo.RepoInfo
578
Active string
579
Issues []db.Issue
580
DidHandleMap map[string]string
···
589
590
type RepoSingleIssueParams struct {
591
LoggedInUser *auth.User
592
+
RepoInfo repoinfo.RepoInfo
593
Active string
594
Issue db.Issue
595
Comments []db.Comment
···
611
612
type RepoNewIssueParams struct {
613
LoggedInUser *auth.User
614
+
RepoInfo repoinfo.RepoInfo
615
Active string
616
}
617
···
622
623
type EditIssueCommentParams struct {
624
LoggedInUser *auth.User
625
+
RepoInfo repoinfo.RepoInfo
626
Issue *db.Issue
627
Comment *db.Comment
628
}
···
634
type SingleIssueCommentParams struct {
635
LoggedInUser *auth.User
636
DidHandleMap map[string]string
637
+
RepoInfo repoinfo.RepoInfo
638
Issue *db.Issue
639
Comment *db.Comment
640
}
···
645
646
type RepoNewPullParams struct {
647
LoggedInUser *auth.User
648
+
RepoInfo repoinfo.RepoInfo
649
Branches []types.Branch
650
Active string
651
}
···
657
658
type RepoPullsParams struct {
659
LoggedInUser *auth.User
660
+
RepoInfo repoinfo.RepoInfo
661
Pulls []*db.Pull
662
Active string
663
DidHandleMap map[string]string
···
689
690
type RepoSinglePullParams struct {
691
LoggedInUser *auth.User
692
+
RepoInfo repoinfo.RepoInfo
693
Active string
694
DidHandleMap map[string]string
695
Pull *db.Pull
···
705
type RepoPullPatchParams struct {
706
LoggedInUser *auth.User
707
DidHandleMap map[string]string
708
+
RepoInfo repoinfo.RepoInfo
709
Pull *db.Pull
710
Diff *types.NiceDiff
711
Round int
···
720
type RepoPullInterdiffParams struct {
721
LoggedInUser *auth.User
722
DidHandleMap map[string]string
723
+
RepoInfo repoinfo.RepoInfo
724
Pull *db.Pull
725
Round int
726
Interdiff *patchutil.InterdiffResult
···
732
}
733
734
type PullPatchUploadParams struct {
735
+
RepoInfo repoinfo.RepoInfo
736
}
737
738
func (p *Pages) PullPatchUploadFragment(w io.Writer, params PullPatchUploadParams) error {
···
740
}
741
742
type PullCompareBranchesParams struct {
743
+
RepoInfo repoinfo.RepoInfo
744
Branches []types.Branch
745
}
746
···
749
}
750
751
type PullCompareForkParams struct {
752
+
RepoInfo repoinfo.RepoInfo
753
Forks []db.Repo
754
}
755
···
758
}
759
760
type PullCompareForkBranchesParams struct {
761
+
RepoInfo repoinfo.RepoInfo
762
SourceBranches []types.Branch
763
TargetBranches []types.Branch
764
}
···
769
770
type PullResubmitParams struct {
771
LoggedInUser *auth.User
772
+
RepoInfo repoinfo.RepoInfo
773
Pull *db.Pull
774
SubmissionId int
775
}
···
780
781
type PullActionsParams struct {
782
LoggedInUser *auth.User
783
+
RepoInfo repoinfo.RepoInfo
784
Pull *db.Pull
785
RoundNumber int
786
MergeCheck types.MergeCheckResponse
···
793
794
type PullNewCommentParams struct {
795
LoggedInUser *auth.User
796
+
RepoInfo repoinfo.RepoInfo
797
Pull *db.Pull
798
RoundNumber int
799
}
+1
-1
appview/pages/templates/repo/blob.html
+1
-1
appview/pages/templates/repo/blob.html
···
42
<span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
43
<span>{{ byteFmt .SizeHint }}</span>
44
<span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
45
-
<a href="/{{ .RepoInfo.FullName }}/blob/{{ .Ref }}/raw/{{ .Path }}">view raw</a>
46
{{ if .RenderToggle }}
47
<span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
48
<a
···
42
<span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
43
<span>{{ byteFmt .SizeHint }}</span>
44
<span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
45
+
<a href="/{{ .RepoInfo.FullName }}/raw/{{ .Ref }}/{{ .Path }}">view raw</a>
46
{{ if .RenderToggle }}
47
<span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
48
<a
+3
-2
appview/state/repo.go
+3
-2
appview/state/repo.go
···
28
"tangled.sh/tangled.sh/core/appview/db"
29
"tangled.sh/tangled.sh/core/appview/pages"
30
"tangled.sh/tangled.sh/core/appview/pages/markup"
31
"tangled.sh/tangled.sh/core/appview/pagination"
32
"tangled.sh/tangled.sh/core/types"
33
···
996
return collaborators, nil
997
}
998
999
-
func (f *FullyResolvedRepo) RepoInfo(s *State, u *auth.User) pages.RepoInfo {
1000
isStarred := false
1001
if u != nil {
1002
isStarred = db.GetStarStatus(s.db, u.Did, syntax.ATURI(f.RepoAt))
···
1070
knot = "tangled.sh"
1071
}
1072
1073
-
repoInfo := pages.RepoInfo{
1074
OwnerDid: f.OwnerDid(),
1075
OwnerHandle: f.OwnerHandle(),
1076
Name: f.RepoName,
···
28
"tangled.sh/tangled.sh/core/appview/db"
29
"tangled.sh/tangled.sh/core/appview/pages"
30
"tangled.sh/tangled.sh/core/appview/pages/markup"
31
+
"tangled.sh/tangled.sh/core/appview/pages/repoinfo"
32
"tangled.sh/tangled.sh/core/appview/pagination"
33
"tangled.sh/tangled.sh/core/types"
34
···
997
return collaborators, nil
998
}
999
1000
+
func (f *FullyResolvedRepo) RepoInfo(s *State, u *auth.User) repoinfo.RepoInfo {
1001
isStarred := false
1002
if u != nil {
1003
isStarred = db.GetStarStatus(s.db, u.Did, syntax.ATURI(f.RepoAt))
···
1071
knot = "tangled.sh"
1072
}
1073
1074
+
repoInfo := repoinfo.RepoInfo{
1075
OwnerDid: f.OwnerDid(),
1076
OwnerHandle: f.OwnerHandle(),
1077
Name: f.RepoName,
+4
-4
appview/state/repo_util.go
+4
-4
appview/state/repo_util.go
···
14
"github.com/go-git/go-git/v5/plumbing/object"
15
"tangled.sh/tangled.sh/core/appview/auth"
16
"tangled.sh/tangled.sh/core/appview/db"
17
-
"tangled.sh/tangled.sh/core/appview/pages"
18
)
19
20
func (s *State) fullyResolvedRepo(r *http.Request) (*FullyResolvedRepo, error) {
···
73
}, nil
74
}
75
76
-
func RolesInRepo(s *State, u *auth.User, f *FullyResolvedRepo) pages.RolesInRepo {
77
if u != nil {
78
r := s.enforcer.GetPermissionsInRepo(u.Did, f.Knot, f.DidSlashRepo())
79
-
return pages.RolesInRepo{r}
80
} else {
81
-
return pages.RolesInRepo{}
82
}
83
}
84
···
14
"github.com/go-git/go-git/v5/plumbing/object"
15
"tangled.sh/tangled.sh/core/appview/auth"
16
"tangled.sh/tangled.sh/core/appview/db"
17
+
"tangled.sh/tangled.sh/core/appview/pages/repoinfo"
18
)
19
20
func (s *State) fullyResolvedRepo(r *http.Request) (*FullyResolvedRepo, error) {
···
73
}, nil
74
}
75
76
+
func RolesInRepo(s *State, u *auth.User, f *FullyResolvedRepo) repoinfo.RolesInRepo {
77
if u != nil {
78
r := s.enforcer.GetPermissionsInRepo(u.Did, f.Knot, f.DidSlashRepo())
79
+
return repoinfo.RolesInRepo{r}
80
} else {
81
+
return repoinfo.RolesInRepo{}
82
}
83
}
84
+1
-1
appview/state/router.go
+1
-1
appview/state/router.go
+4
-1
knotserver/handler.go
+4
-1
knotserver/handler.go