forked from tangled.org/core
this repo has no description

appview: pages/markup: serve relative images directly from the knot

authored by anirudh.fi and committed by Tangled e53a3a38 ba0c65a2

Changed files
+108 -160
appview
pages
markup
templates
repo
state
knotserver
+2
.gitignore
··· 7 result 8 !.gitkeep 9 out/
··· 7 result 8 !.gitkeep 9 out/ 10 + ./camo/node_modules/* 11 +
+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
··· 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
··· 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
··· 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
··· 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
··· 65 r.Get("/branches", s.RepoBranches) 66 r.Get("/tags", s.RepoTags) 67 r.Get("/blob/{ref}/*", s.RepoBlob) 68 - r.Get("/blob/{ref}/raw/*", s.RepoBlobRaw) 69 70 r.Route("/issues", func(r chi.Router) { 71 r.With(middleware.Paginate).Get("/", s.RepoIssues)
··· 65 r.Get("/branches", s.RepoBranches) 66 r.Get("/tags", s.RepoTags) 67 r.Get("/blob/{ref}/*", s.RepoBlob) 68 + r.Get("/raw/{ref}/*", s.RepoBlobRaw) 69 70 r.Route("/issues", func(r chi.Router) { 71 r.With(middleware.Paginate).Get("/", s.RepoIssues)
+4 -1
knotserver/handler.go
··· 100 101 r.Route("/blob/{ref}", func(r chi.Router) { 102 r.Get("/*", h.Blob) 103 - r.Get("/raw/*", h.BlobRaw) 104 }) 105 106 r.Get("/log/{ref}", h.Log)
··· 100 101 r.Route("/blob/{ref}", func(r chi.Router) { 102 r.Get("/*", h.Blob) 103 + }) 104 + 105 + r.Route("/raw/{ref}", func(r chi.Router) { 106 + r.Get("/*", h.BlobRaw) 107 }) 108 109 r.Get("/log/{ref}", h.Log)